Skip to content

Commit

Permalink
Merge pull request #1115 from radixdlt/sp/ABW-3645-seed-phrase-ui-ref…
Browse files Browse the repository at this point in the history
…inements

[ABW-3645] - Seed phrase UI refinements
  • Loading branch information
sergiupuhalschi-rdx authored Aug 6, 2024
2 parents f2718f6 + 781bde1 commit 3ee9741
Show file tree
Hide file tree
Showing 18 changed files with 354 additions and 293 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
Expand Down Expand Up @@ -43,6 +44,7 @@ import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAp
import com.babylon.wallet.android.presentation.ui.composables.RadixSnackbarHost
import com.babylon.wallet.android.presentation.ui.composables.SnackbarUIMessage
import com.babylon.wallet.android.presentation.ui.composables.statusBarsAndBanner
import com.babylon.wallet.android.presentation.ui.composables.utils.isKeyboardVisible
import com.babylon.wallet.android.utils.biometricAuthenticateSuspend
import com.radixdlt.sargon.AccountAddress

Expand Down Expand Up @@ -135,7 +137,7 @@ fun CreateAccountContent(
)

Scaffold(
modifier = modifier.imePadding(),
modifier = modifier,
topBar = {
RadixCenteredTopAppBar(
title = stringResource(id = R.string.empty),
Expand All @@ -148,7 +150,8 @@ fun CreateAccountContent(
RadixBottomBar(
onClick = { onAccountCreateClick(isWithLedger) },
text = stringResource(id = R.string.createAccount_nameNewAccount_continue),
enabled = buttonEnabled
enabled = buttonEnabled,
insets = if (isKeyboardVisible()) WindowInsets.ime else WindowInsets.navigationBars
)
},
containerColor = RadixTheme.colors.defaultBackground,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,10 @@ class SeedPhraseInputDelegate(
}

@Suppress("LongMethod")
fun onWordChanged(index: Int, value: String, onMoveToNextWord: suspend () -> Unit) {
val isDeleting = (_state.value.seedPhraseWords.firstOrNull { it.index == index }?.value?.length ?: 0) > value.length
fun onWordChanged(index: Int, value: String) {
_state.update { state ->
val updatedWords = state.seedPhraseWords.mapWhen(predicate = { it.index == index }, mutation = {
it.copy(value = value)
it.copy(value = value.trim())
}).toPersistentList()
state.copy(
seedPhraseWords = updatedWords,
Expand All @@ -86,41 +85,31 @@ class SeedPhraseInputDelegate(
return@launch
}
}
var shouldMoveToNextWord = false
val wordCandidates = if (value.isEmpty()) {
emptyList()
} else {
englishWordList.filter { it.startsWith(value) }
}
val newValue = if (wordCandidates.size == 1 && !isDeleting) {
shouldMoveToNextWord = true
wordCandidates[0]
} else {
value
}

val wordState = when {
wordCandidates.contains(newValue) -> SeedPhraseWord.State.Valid
newValue.isEmpty() -> SeedPhraseWord.State.Empty
wordCandidates.contains(value) -> SeedPhraseWord.State.Valid
value.isEmpty() -> SeedPhraseWord.State.Empty
wordCandidates.isEmpty() -> SeedPhraseWord.State.Invalid
else -> SeedPhraseWord.State.HasValue
}
_state.update { state ->
val updatedWords = state.seedPhraseWords.mapWhen(predicate = { it.index == index }, mutation = {
it.copy(value = newValue, state = wordState)
it.copy(value = value.trim(), state = wordState)
}).toPersistentList()
state.copy(
seedPhraseWords = updatedWords,
wordAutocompleteCandidates = wordCandidates.toPersistentList()
wordAutocompleteCandidates = if (wordCandidates.size == 1 && wordCandidates.first() == value) {
emptyList()
} else {
wordCandidates
}.toPersistentList()
)
}
if (shouldMoveToNextWord) {
_state.update {
it.copy(wordAutocompleteCandidates = persistentListOf())
}
if (index != _state.value.seedPhraseWords.lastIndex) {
onMoveToNextWord()
}
}
}
}

Expand All @@ -137,7 +126,7 @@ class SeedPhraseInputDelegate(
data class State(
val bip39Passphrase: String = "",
val seedPhraseWords: ImmutableList<SeedPhraseWord> = persistentListOf(),
val wordAutocompleteCandidates: ImmutableList<String> = persistentListOf(),
val wordAutocompleteCandidates: ImmutableList<String> = persistentListOf()
) : UiState {

private val isInputEmpty: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ fun NavGraphBuilder.addSingleMnemonic(
}
),
enterTransition = {
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up)
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left)
},
exitTransition = {
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down)
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right)
},
popEnterTransition = {
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Right)
}
) {
AddSingleMnemonicScreen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentWidth
Expand All @@ -26,7 +25,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -35,7 +33,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
Expand All @@ -58,6 +55,9 @@ import com.babylon.wallet.android.presentation.ui.composables.SeedPhraseSuggesti
import com.babylon.wallet.android.presentation.ui.composables.SnackbarUIMessage
import com.babylon.wallet.android.presentation.ui.composables.WarningText
import com.babylon.wallet.android.presentation.ui.composables.statusBarsAndBanner
import com.babylon.wallet.android.presentation.ui.composables.utils.HideKeyboardOnFullScroll
import com.babylon.wallet.android.presentation.ui.composables.utils.isKeyboardVisible
import com.babylon.wallet.android.presentation.ui.modifier.dynamicImePadding
import com.babylon.wallet.android.utils.BiometricAuthenticationResult
import com.babylon.wallet.android.utils.biometricAuthenticate
import com.radixdlt.sargon.Bip39WordCount
Expand Down Expand Up @@ -145,7 +145,7 @@ private fun AddSingleMnemonicsContent(
modifier = Modifier
.fillMaxWidth()
.imePadding()
.height(56.dp)
.height(RadixTheme.dimensions.seedPhraseWordsSuggestionsHeight)
.padding(RadixTheme.dimensions.paddingSmall),
onCandidateClick = { candidate ->
focusedWordIndex?.let {
Expand All @@ -155,12 +155,11 @@ private fun AddSingleMnemonicsContent(
}
)
} else {
val isEnabled = remember(state.seedPhraseState) {
state.seedPhraseState.isValidSeedPhrase()
}
RadixBottomBar(
text = stringResource(R.string.common_continue),
enabled = isEnabled,
enabled = remember(state.seedPhraseState) {
state.seedPhraseState.isValidSeedPhrase()
},
onClick = onSubmitClick
)
}
Expand All @@ -182,7 +181,14 @@ private fun AddSingleMnemonicsContent(
SeedPhraseView(
modifier = Modifier
.fillMaxSize()
.padding(padding),
.dynamicImePadding(
padding = padding,
keyboardVisibleBottomPadding = if (isSuggestionsVisible(state)) {
RadixTheme.dimensions.seedPhraseWordsSuggestionsHeight + RadixTheme.dimensions.paddingDefault
} else {
RadixTheme.dimensions.paddingDefault
}
),
title = title,
onWordChanged = onWordTyped,
onPassphraseChanged = onPassphraseChanged,
Expand All @@ -206,10 +212,15 @@ private fun SeedPhraseView(
isOlympia: Boolean
) {
SecureScreen()

val scrollState = rememberScrollState()
HideKeyboardOnFullScroll(scrollState)

Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.imePadding()
.verticalScroll(scrollState)
) {
Text(
modifier = Modifier
Expand Down Expand Up @@ -319,12 +330,7 @@ private fun SeedPhraseView(

@Composable
private fun isSuggestionsVisible(state: AddSingleMnemonicViewModel.State): Boolean {
val density = LocalDensity.current
val imeInsets = WindowInsets.ime
val keyboardVisible by remember {
derivedStateOf { imeInsets.getBottom(density) > 0 }
}
return state.seedPhraseState.wordAutocompleteCandidates.isNotEmpty() && keyboardVisible
return state.seedPhraseState.wordAutocompleteCandidates.isNotEmpty() && isKeyboardVisible()
}

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ class AddSingleMnemonicViewModel @Inject constructor(
}

fun onWordChanged(index: Int, value: String) {
seedPhraseInputDelegate.onWordChanged(index, value) {
sendEvent(Event.MoveToNextWord)
}
seedPhraseInputDelegate.onWordChanged(index, value)
}

fun onWordSelected(index: Int, value: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ fun NavGraphBuilder.restoreMnemonicsScreen(
}
),
enterTransition = {
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up)
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left)
},
exitTransition = {
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down)
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right)
},
popExitTransition = {
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Left)
}
) {
RestoreMnemonicsScreen(
Expand Down
Loading

0 comments on commit 3ee9741

Please sign in to comment.