Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-19 13:01:32 +03:00
parent 4430add6f0
commit 66aedc97cb
10 changed files with 192 additions and 28 deletions

View file

@ -5,6 +5,9 @@ import com.tangem.crypto.bip39.Mnemonic
import com.tangem.crypto.bip39.MnemonicErrorResult
import com.tangem.feature.onboarding.data.MnemonicRepository
import com.tangem.utils.extensions.isNotWhitespace
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
/**
[REDACTED_AUTHOR]
@ -58,14 +61,18 @@ internal class DefaultSeedPhraseInteractor constructor(
}
}
override suspend fun getSuggestions(text: String, hasSelection: Boolean, cursorPosition: Int): List<String> {
if (text.isEmpty() || cursorPosition == 0 || hasSelection) return emptyList()
override suspend fun getSuggestions(
text: String,
hasSelection: Boolean,
cursorPosition: Int,
): ImmutableList<String> {
if (text.isEmpty() || cursorPosition == 0 || hasSelection) return persistentListOf()
val word = partWordFinder.getLeadPartOfWord(text, cursorPosition)
?: return emptyList()
?: return persistentListOf()
val suggestions = repository.getWordsDictionary()
.filter { it.startsWith(word, ignoreCase = false) && it != word }
.toList()
.toPersistentList()
return suggestions
}

View file

@ -1,6 +1,7 @@
package com.tangem.feature.onboarding.domain
import com.tangem.crypto.bip39.Mnemonic
import kotlinx.collections.immutable.ImmutableList
/**
[REDACTED_AUTHOR]
@ -10,7 +11,7 @@ interface SeedPhraseInteractor {
suspend fun getMnemonicComponents(): Result<List<String>>
suspend fun isWordMatch(word: String): Boolean
suspend fun validateMnemonicString(text: String): Result<List<String>>
suspend fun getSuggestions(text: String, hasSelection: Boolean, cursorPosition: Int): List<String>
suspend fun getSuggestions(text: String, hasSelection: Boolean, cursorPosition: Int): ImmutableList<String>
suspend fun insertSuggestionWord(text: String, suggestion: String, cursorPosition: Int): InsertSuggestionResult
companion object {

View file

@ -52,7 +52,7 @@ data class ImportSeedPhraseState(
val onSuggestedPhraseClick: (Int) -> Unit,
val buttonCreateWallet: ButtonState,
val invalidWords: Set<String> = emptySet(),
val suggestionsList: List<String> = emptyList(),
val suggestionsList: ImmutableList<String> = persistentListOf(),
val error: SeedPhraseError? = null,
)

View file

@ -1,6 +1,7 @@
package com.tangem.feature.onboarding.presentation.wallet2.ui
import androidx.compose.animation.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material.OutlinedTextField
@ -11,10 +12,15 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.Notifier
import com.tangem.core.ui.components.PrimaryButtonIconStart
import com.tangem.core.ui.components.TangemTextFieldsDefault
import com.tangem.core.ui.components.buttons.common.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.onboarding.R
import com.tangem.feature.onboarding.presentation.wallet2.model.ImportSeedPhraseState
@ -23,6 +29,8 @@ import com.tangem.feature.onboarding.presentation.wallet2.ui.components.Onboardi
import com.tangem.feature.onboarding.presentation.wallet2.ui.components.OnboardingDescriptionBlock
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.InvalidWordsColorTransformation
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseErrorConverter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
/**
[REDACTED_AUTHOR]
@ -48,7 +56,9 @@ fun ImportSeedPhraseScreen(state: ImportSeedPhraseState, modifier: Modifier = Mo
state = state,
)
SuggestionsBlock(
state = state,
modifier = Modifier.padding(top = TangemTheme.dimens.size4),
suggestionsList = state.suggestionsList,
onClick = { index -> state.onSuggestedPhraseClick(index) },
)
}
}
@ -114,25 +124,86 @@ private fun PhraseBlock(state: ImportSeedPhraseState, modifier: Modifier = Modif
@Suppress("ReusedModifierInstance")
@Composable
private fun SuggestionsBlock(state: ImportSeedPhraseState, modifier: Modifier = Modifier) {
private fun SuggestionsBlock(
suggestionsList: ImmutableList<String>,
onClick: (Int) -> Unit,
modifier: Modifier = Modifier,
) {
AnimatedVisibility(
enter = fadeIn() + slideIn(initialOffset = { IntOffset(x = 200, y = 0) }),
exit = slideOut(targetOffset = { IntOffset(x = -200, y = 0) }) + fadeOut(),
visible = state.suggestionsList.isNotEmpty(),
visible = suggestionsList.isNotEmpty(),
) {
LazyRow(
modifier = modifier.fillMaxSize(),
modifier = modifier,
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.size16),
) {
items(state.suggestionsList.size) { index ->
PrimaryButton(
modifier = Modifier
.height(TangemTheme.dimens.size46)
.padding(all = TangemTheme.dimens.size4),
text = state.suggestionsList[index],
onClick = { state.onSuggestedPhraseClick(index) },
items(suggestionsList.size) { index ->
SuggestionButton(
modifier = Modifier.rowPadding(
index = index,
rowSize = suggestionsList.size,
outSide = TangemTheme.dimens.size0,
inSide = TangemTheme.dimens.size4,
),
text = suggestionsList[index],
onClick = { onClick(index) },
)
}
}
}
}
}
@Composable
private fun SuggestionButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier) {
Box(modifier = modifier.clickable(onClick = onClick)) {
Notifier(
text = text,
backgroundColor = TangemTheme.colors.background.action,
textColor = TangemTheme.colors.text.primary2,
)
}
}
private fun Modifier.rowPadding(index: Int, rowSize: Int, outSide: Dp, inSide: Dp): Modifier = when (index) {
0 -> this.padding(start = outSide, end = inSide)
rowSize - 1 -> this.padding(start = inSide, end = outSide)
else -> this.padding(horizontal = inSide)
}
@Preview
@Composable
private fun SuggestionsBlockPreview_Light(
@PreviewParameter(SuggestionsPreviewParamsProvider::class) suggestions: ImmutableList<String>,
) {
TangemTheme(isDark = false) {
SuggestionsBlock(
suggestionsList = suggestions,
onClick = {},
)
}
}
@Preview
@Composable
private fun SuggestionsBlockPreview_Dark(
@PreviewParameter(SuggestionsPreviewParamsProvider::class) suggestions: ImmutableList<String>,
) {
TangemTheme(isDark = true) {
SuggestionsBlock(
suggestionsList = suggestions,
onClick = {},
)
}
}
private class SuggestionsPreviewParamsProvider : CollectionPreviewParameterProvider<ImmutableList<String>>(
collection = listOf(
persistentListOf(
"one",
"each",
"explorer",
"unknown",
),
),
)

View file

@ -5,6 +5,7 @@ import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.onboarding.domain.InsertSuggestionResult
import com.tangem.feature.onboarding.domain.SeedPhraseError
import com.tangem.feature.onboarding.presentation.wallet2.model.OnboardingSeedPhraseState
import kotlinx.collections.immutable.ImmutableList
/**
[REDACTED_AUTHOR]
@ -39,12 +40,14 @@ class ImportSeedPhraseStateBuilder {
),
)
fun updateSuggestions(uiState: OnboardingSeedPhraseState, suggestions: List<String>): OnboardingSeedPhraseState =
uiState.copy(
importSeedPhraseState = uiState.importSeedPhraseState.copy(
suggestionsList = suggestions,
),
)
fun updateSuggestions(
uiState: OnboardingSeedPhraseState,
suggestions: ImmutableList<String>,
): OnboardingSeedPhraseState = uiState.copy(
importSeedPhraseState = uiState.importSeedPhraseState.copy(
suggestionsList = suggestions,
),
)
fun insertSuggestionWord(
uiState: OnboardingSeedPhraseState,

View file

@ -22,6 +22,7 @@ import com.tangem.utils.coroutines.Debouncer
import com.tangem.utils.extensions.isEven
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
@ -373,7 +374,7 @@ class SeedPhraseViewModel @Inject constructor(
)
updateUi {
val mediateState = uiBuilder.importSeedPhrase.insertSuggestionWord(uiState, insertResult)
uiBuilder.importSeedPhrase.updateSuggestions(mediateState, emptyList())
uiBuilder.importSeedPhrase.updateSuggestions(mediateState, persistentListOf())
}
}
}