Updated on 2026-08-14
This commit is contained in:
parent
4e0089d3d2
commit
a85078c180
8 changed files with 85 additions and 42 deletions
|
|
@ -9,7 +9,7 @@ import com.tangem.sdk.extensions.getWordlist
|
|||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class MnemonicRepository @Inject constructor(
|
||||
internal class MnemonicRepository @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
) {
|
||||
private val wordlist = Wordlist.getWordlist(context)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
|
||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||
private val multiWalletState get() = params.multiWalletState
|
||||
private val state = MutableStateFlow(SeedPhraseState())
|
||||
private val _uiState = MutableStateFlow(getStartState())
|
||||
private val state = MutableStateFlow(getInitialSeedPhraseState())
|
||||
private val _uiState = MutableStateFlow(getInitialUIState())
|
||||
|
||||
private val generateSeedPhraseUiStateBuilder = GenerateSeedPhraseUiStateBuilder(
|
||||
updateUiState = { block -> updateUiStateSpecific(block) },
|
||||
|
|
@ -60,7 +60,9 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
// =============================================
|
||||
// | DON'T FIXME !!! MODIFY WITH CAUTION !!! |
|
||||
// =============================================
|
||||
changeWords24Option = { state.update { it.copy(words24Option = it.words24Option) } },
|
||||
changeGeneratedWordsType = { newType ->
|
||||
state.update { st -> st.copy(generatedWordsType = newType) }
|
||||
},
|
||||
// =============================================
|
||||
)
|
||||
|
||||
|
|
@ -75,10 +77,9 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
// =============================================
|
||||
importWallet = importWallet@{
|
||||
importWallet(
|
||||
mnemonic = if (state.value.words24Option) {
|
||||
state.value.generatedWords24 ?: return@importWallet
|
||||
} else {
|
||||
state.value.generatedWords12 ?: return@importWallet
|
||||
mnemonic = when (state.value.generatedWordsType) {
|
||||
GeneratedWordsType.Words12 -> state.value.generatedWords12 ?: return@importWallet
|
||||
GeneratedWordsType.Words24 -> state.value.generatedWords24 ?: return@importWallet
|
||||
},
|
||||
passphrase = null,
|
||||
generatedSeedPhrase = true,
|
||||
|
|
@ -91,6 +92,7 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
modelScope = modelScope,
|
||||
mnemonicRepository = mnemonicRepository,
|
||||
updateUiState = { block -> updateUiStateSpecific(block) },
|
||||
readyToImport = { ready -> state.update { it.copy(readyToImport = ready) } },
|
||||
importWallet = { mnemonic, passphrase ->
|
||||
importWallet(
|
||||
mnemonic = mnemonic,
|
||||
|
|
@ -112,8 +114,8 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
is MultiWalletSeedPhraseUM.Import,
|
||||
is MultiWalletSeedPhraseUM.GenerateSeedPhrase,
|
||||
-> {
|
||||
_uiState.value = getStartState()
|
||||
state.value = SeedPhraseState()
|
||||
_uiState.value = getInitialUIState()
|
||||
state.value = getInitialSeedPhraseState()
|
||||
}
|
||||
is MultiWalletSeedPhraseUM.GeneratedWordsCheck -> {
|
||||
openGeneratedSeedPhrase()
|
||||
|
|
@ -121,7 +123,16 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getStartState(): MultiWalletSeedPhraseUM {
|
||||
private fun getInitialSeedPhraseState(): SeedPhraseState {
|
||||
return SeedPhraseState(
|
||||
generatedWords12 = null,
|
||||
generatedWords24 = null,
|
||||
generatedWordsType = GeneratedWordsType.Words12,
|
||||
readyToImport = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getInitialUIState(): MultiWalletSeedPhraseUM {
|
||||
return MultiWalletSeedPhraseUM.Start(
|
||||
onImportSeedPhraseClicked = {
|
||||
openImportSeedPhrase()
|
||||
|
|
@ -143,6 +154,7 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
_uiState.value = generateSeedPhraseUiStateBuilder.getState(
|
||||
generatedWords12 = words12,
|
||||
generatedWords24 = words24,
|
||||
option = state.value.generatedWordsType,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.mode
|
|||
|
||||
import com.tangem.crypto.bip39.Mnemonic
|
||||
|
||||
data class SeedPhraseState(
|
||||
val generatedWords12: Mnemonic? = null,
|
||||
val generatedWords24: Mnemonic? = null,
|
||||
val words24Option: Boolean = false,
|
||||
val readyToImport: Boolean = false,
|
||||
)
|
||||
internal data class SeedPhraseState(
|
||||
val generatedWords12: Mnemonic?,
|
||||
val generatedWords24: Mnemonic?,
|
||||
val generatedWordsType: GeneratedWordsType,
|
||||
val readyToImport: Boolean,
|
||||
)
|
||||
|
||||
internal enum class GeneratedWordsType(val length: Int) {
|
||||
Words12(12),
|
||||
Words24(24),
|
||||
}
|
||||
|
|
@ -1,19 +1,24 @@
|
|||
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.GeneratedWordsType
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class GenerateSeedPhraseUiStateBuilder(
|
||||
private val changeWords24Option: (Boolean) -> Unit,
|
||||
private val changeGeneratedWordsType: (GeneratedWordsType) -> Unit,
|
||||
private val updateUiState: (
|
||||
(MultiWalletSeedPhraseUM.GenerateSeedPhrase) -> MultiWalletSeedPhraseUM.GenerateSeedPhrase,
|
||||
) -> Unit,
|
||||
private val onContinue: () -> Unit,
|
||||
) {
|
||||
|
||||
fun getState(generatedWords12: Mnemonic, generatedWords24: Mnemonic): MultiWalletSeedPhraseUM.GenerateSeedPhrase {
|
||||
fun getState(
|
||||
generatedWords12: Mnemonic,
|
||||
generatedWords24: Mnemonic,
|
||||
option: GeneratedWordsType,
|
||||
): MultiWalletSeedPhraseUM.GenerateSeedPhrase {
|
||||
val words12 = generatedWords12.mnemonicComponents.mapIndexed { index, s ->
|
||||
MultiWalletSeedPhraseUM.GenerateSeedPhrase.MnemonicGridItem(index + 1, s)
|
||||
}.toImmutableList()
|
||||
|
|
@ -22,26 +27,35 @@ internal class GenerateSeedPhraseUiStateBuilder(
|
|||
}.toImmutableList()
|
||||
|
||||
return MultiWalletSeedPhraseUM.GenerateSeedPhrase(
|
||||
words24OptionSelected = false,
|
||||
words = words12,
|
||||
onWords24OptionSwitch = { switchType(words12, words24) },
|
||||
option = option,
|
||||
words = when (option) {
|
||||
GeneratedWordsType.Words12 -> words12
|
||||
GeneratedWordsType.Words24 -> words24
|
||||
},
|
||||
onOptionChange = {
|
||||
switchType(
|
||||
newType = it,
|
||||
generatedWords12 = words12,
|
||||
generatedWords24 = words24,
|
||||
)
|
||||
},
|
||||
onContinueClick = onContinue,
|
||||
)
|
||||
}
|
||||
|
||||
private fun switchType(
|
||||
newType: GeneratedWordsType,
|
||||
generatedWords12: ImmutableList<MultiWalletSeedPhraseUM.GenerateSeedPhrase.MnemonicGridItem>,
|
||||
generatedWords24: ImmutableList<MultiWalletSeedPhraseUM.GenerateSeedPhrase.MnemonicGridItem>,
|
||||
) {
|
||||
updateUiState { uiSt ->
|
||||
changeWords24Option(uiSt.words24OptionSelected.not())
|
||||
changeGeneratedWordsType(newType)
|
||||
|
||||
uiSt.copy(
|
||||
words24OptionSelected = uiSt.words24OptionSelected.not(),
|
||||
words = if (uiSt.words24OptionSelected) {
|
||||
generatedWords12
|
||||
} else {
|
||||
generatedWords24
|
||||
option = newType,
|
||||
words = when (newType) {
|
||||
GeneratedWordsType.Words12 -> generatedWords12
|
||||
GeneratedWordsType.Words24 -> generatedWords24
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.launch
|
|||
internal class ImportSeedPhraseUiStateBuilder(
|
||||
private val modelScope: CoroutineScope,
|
||||
private val mnemonicRepository: MnemonicRepository,
|
||||
private val readyToImport: (Boolean) -> Unit,
|
||||
private val updateUiState: ((MultiWalletSeedPhraseUM.Import) -> MultiWalletSeedPhraseUM.Import) -> Unit,
|
||||
private val importWallet: (mnemonic: Mnemonic, passphrase: String?) -> Unit,
|
||||
) {
|
||||
|
|
@ -100,6 +101,8 @@ internal class ImportSeedPhraseUiStateBuilder(
|
|||
}
|
||||
|
||||
private fun interceptWords(wordsField: TextFieldValue) {
|
||||
readyToImport(false)
|
||||
|
||||
updateUiState {
|
||||
it.copy(
|
||||
createWalletEnabled = false,
|
||||
|
|
@ -133,7 +136,9 @@ internal class ImportSeedPhraseUiStateBuilder(
|
|||
createWalletEnabled = true,
|
||||
)
|
||||
}
|
||||
readyToImport(true)
|
||||
} catch (ex: TangemSdkError.MnemonicException) {
|
||||
readyToImport(false)
|
||||
val error = ex.mnemonicResult
|
||||
if (error is MnemonicErrorResult.InvalidChecksum) {
|
||||
updateUiState {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.builder
|
||||
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.GeneratedWordsType
|
||||
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
|
||||
|
|
@ -93,10 +94,9 @@ internal class SeedPhraseCheckUiStateBuilder(
|
|||
currentState.generatedWords12 ?: return false
|
||||
currentState.generatedWords24 ?: return false
|
||||
|
||||
val wordList = if (currentState.words24Option) {
|
||||
currentState.generatedWords24
|
||||
} else {
|
||||
currentState.generatedWords12
|
||||
val wordList = when (currentState.generatedWordsType) {
|
||||
GeneratedWordsType.Words12 -> currentState.generatedWords12
|
||||
GeneratedWordsType.Words24 -> currentState.generatedWords24
|
||||
}.mnemonicComponents
|
||||
|
||||
return wordList[shownIndex - 1] == word
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.GeneratedWordsType
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM.GenerateSeedPhrase.MnemonicGridItem
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -67,19 +68,24 @@ internal fun MultiWalletSeedPhraseWords(
|
|||
private fun SegmentSeedBlock(state: MultiWalletSeedPhraseUM.GenerateSeedPhrase, modifier: Modifier = Modifier) {
|
||||
SegmentedButtons(
|
||||
modifier = modifier.padding(horizontal = TangemTheme.dimens.spacing76),
|
||||
config = persistentListOf(0, 1),
|
||||
initialSelectedItem = if (state.words24OptionSelected.not()) 0 else 1,
|
||||
config = persistentListOf(GeneratedWordsType.Words12, GeneratedWordsType.Words24),
|
||||
initialSelectedItem = state.option,
|
||||
onClick = {
|
||||
if (state.words24OptionSelected && it == 0 || state.words24OptionSelected.not() && it == 1) {
|
||||
state.onWords24OptionSwitch()
|
||||
when {
|
||||
state.option == GeneratedWordsType.Words12 && it == GeneratedWordsType.Words24 -> {
|
||||
state.onOptionChange(it)
|
||||
}
|
||||
state.option == GeneratedWordsType.Words24 && it == GeneratedWordsType.Words12 -> {
|
||||
state.onOptionChange(it)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = pluralStringResourceSafe(
|
||||
id = R.plurals.onboarding_seed_generate_words_count,
|
||||
count = if (it == 0) 12 else 24,
|
||||
if (it == 0) 12 else 24,
|
||||
count = state.option.length,
|
||||
state.option.length,
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(vertical = TangemTheme.dimens.spacing10)
|
||||
|
|
@ -110,8 +116,8 @@ private fun TitleBlock(state: MultiWalletSeedPhraseUM.GenerateSeedPhrase, modifi
|
|||
Text(
|
||||
text = pluralStringResourceSafe(
|
||||
id = R.plurals.onboarding_seed_generate_message_words_count,
|
||||
count = if (state.words24OptionSelected.not()) 12 else 24,
|
||||
if (state.words24OptionSelected.not()) 12 else 24,
|
||||
count = state.option.length,
|
||||
state.option.length,
|
||||
),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
|
|||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.GeneratedWordsType
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -20,9 +21,9 @@ internal sealed class MultiWalletSeedPhraseUM(
|
|||
) : MultiWalletSeedPhraseUM(order = 0)
|
||||
|
||||
data class GenerateSeedPhrase(
|
||||
val words24OptionSelected: Boolean = false,
|
||||
val option: GeneratedWordsType = GeneratedWordsType.Words12,
|
||||
val words: ImmutableList<MnemonicGridItem> = persistentListOf(),
|
||||
val onWords24OptionSwitch: () -> Unit = {},
|
||||
val onOptionChange: (GeneratedWordsType) -> Unit = {},
|
||||
val onContinueClick: () -> Unit = {},
|
||||
) : MultiWalletSeedPhraseUM(order = 1) {
|
||||
data class MnemonicGridItem(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue