Updated on 2026-08-14
This commit is contained in:
parent
6ba6358b86
commit
67a80fc097
6 changed files with 103 additions and 11 deletions
|
|
@ -11,4 +11,8 @@ internal data class CustomTokenData(
|
|||
return contractAddressTextField.isInputValid() && nameTextField.isInputValid() &&
|
||||
symbolTextField.isInputValid() && decimalsTextField.isInputValid()
|
||||
}
|
||||
|
||||
fun isNameSymbolDecimalsDisabled(): Boolean {
|
||||
return nameTextField.isDisabled() && symbolTextField.isDisabled() && decimalsTextField.isDisabled()
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,8 @@ internal sealed class TextFieldState {
|
|||
|
||||
fun isInputValid(): Boolean = this is Editable && value.isNotBlank() && error == null
|
||||
|
||||
fun isDisabled() = this is Editable && !this.isEnabled
|
||||
|
||||
fun copySealed(
|
||||
value: String = (this as? Editable)?.value ?: "",
|
||||
isEnabled: Boolean = (this as? Editable)?.isEnabled ?: true,
|
||||
|
|
|
|||
|
|
@ -176,6 +176,32 @@ internal class AddCustomTokenStateFactory(
|
|||
return currentStateProvider().copy(tokenData = tokenData.copy(contractAddressTextField = contractAddressField))
|
||||
}
|
||||
|
||||
private fun unlockAndClearNameSymbolAndDecimals(state: AddCustomTokenState): AddCustomTokenState {
|
||||
val currentTokenData = state.tokenData
|
||||
return state.copy(
|
||||
tokenData = currentTokenData?.copy(
|
||||
nameTextField = TextFieldState.Editable(
|
||||
value = "",
|
||||
isEnabled = true,
|
||||
onValueChange = clickIntents::onTokenNameChange,
|
||||
onFocusExit = clickIntents::onTokenNameFocusExit,
|
||||
),
|
||||
symbolTextField = TextFieldState.Editable(
|
||||
value = "",
|
||||
isEnabled = true,
|
||||
onValueChange = clickIntents::onSymbolChange,
|
||||
onFocusExit = clickIntents::onSymbolFocusExit,
|
||||
),
|
||||
decimalsTextField = TextFieldState.Editable(
|
||||
value = "",
|
||||
isEnabled = true,
|
||||
onValueChange = clickIntents::onDecimalsChange,
|
||||
onFocusExit = clickIntents::onDecimalsFocusExit,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun getStateAndTriggerEvent(
|
||||
state: AddCustomTokenState,
|
||||
event: Event,
|
||||
|
|
@ -286,7 +312,7 @@ internal class AddCustomTokenStateFactory(
|
|||
val uiState = currentStateProvider()
|
||||
return when (error) {
|
||||
AddCustomTokenError.INVALID_CONTRACT_ADDRESS -> {
|
||||
addTokenAddressFieldError(AddCustomTokenWarning.InvalidContractAddress)
|
||||
removeTokenAddressError().also { unlockAndClearNameSymbolAndDecimals(it) }
|
||||
.copy(
|
||||
addTokenButton = uiState.addTokenButton.copy(isEnabled = false),
|
||||
warnings = uiState.warnings
|
||||
|
|
@ -295,7 +321,7 @@ internal class AddCustomTokenStateFactory(
|
|||
)
|
||||
}
|
||||
AddCustomTokenError.FIELD_IS_EMPTY ->
|
||||
removeTokenAddressError()
|
||||
removeTokenAddressError().also { unlockAndClearNameSymbolAndDecimals(it) }
|
||||
.copy(
|
||||
addTokenButton = uiState.addTokenButton.copy(
|
||||
isEnabled = uiState.tokenData?.isRequiredInformationProvided() == true,
|
||||
|
|
|
|||
|
|
@ -4,11 +4,16 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -154,8 +159,11 @@ private fun ColumnScope.CustomTokenItemsList(state: AddCustomTokenState, modifie
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
private fun TokenFields(state: CustomTokenData, modifier: Modifier = Modifier) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -166,21 +174,51 @@ private fun TokenFields(state: CustomTokenData, modifier: Modifier = Modifier) {
|
|||
textFieldState = state.contractAddressTextField,
|
||||
placeholder = "0x0000000000000000000000000000000",
|
||||
title = R.string.custom_token_contract_address_input_title,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = if (state.isNameSymbolDecimalsDisabled()) {
|
||||
ImeAction.Done
|
||||
} else {
|
||||
ImeAction.Next
|
||||
},
|
||||
),
|
||||
onImeAction = {
|
||||
if (state.isNameSymbolDecimalsDisabled()) {
|
||||
focusManager.moveFocus(FocusDirection.Exit)
|
||||
} else {
|
||||
focusManager.moveFocus(FocusDirection.Down)
|
||||
}
|
||||
},
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.nameTextField,
|
||||
placeholder = stringResource(id = R.string.custom_token_name_input_placeholder),
|
||||
title = R.string.custom_token_name_input_title,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Next,
|
||||
),
|
||||
onImeAction = { focusManager.moveFocus(FocusDirection.Down) },
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.symbolTextField,
|
||||
placeholder = stringResource(id = R.string.custom_token_token_symbol_input_placeholder),
|
||||
title = R.string.custom_token_token_symbol_input_title,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Next,
|
||||
),
|
||||
onImeAction = { focusManager.moveFocus(FocusDirection.Down) },
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.decimalsTextField,
|
||||
placeholder = "0",
|
||||
title = R.string.custom_token_decimals_input_title,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Number,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
onImeAction = { focusManager.moveFocus(FocusDirection.Exit) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +228,8 @@ private fun TokenField(
|
|||
textFieldState: TextFieldState,
|
||||
placeholder: String,
|
||||
title: Int,
|
||||
keyboardType: KeyboardType = KeyboardType.Text,
|
||||
onImeAction: () -> Unit,
|
||||
keyboardOptions: KeyboardOptions,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
@ -205,7 +244,8 @@ private fun TokenField(
|
|||
is TextFieldState.Editable -> TokenTextField(
|
||||
state = textFieldState,
|
||||
placeholder = placeholder,
|
||||
keyboardType = keyboardType,
|
||||
onImeAction = onImeAction,
|
||||
keyboardOptions = keyboardOptions,
|
||||
)
|
||||
is TextFieldState.Loading -> TokenShimmer()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.input.key.*
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
|
|
@ -22,7 +23,11 @@ import com.tangem.managetokens.presentation.addcustomtoken.state.TextFieldState
|
|||
internal fun TokenTextField(
|
||||
state: TextFieldState.Editable,
|
||||
placeholder: String,
|
||||
keyboardType: KeyboardType = KeyboardType.Text,
|
||||
onImeAction: () -> Unit,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Default,
|
||||
),
|
||||
) {
|
||||
val isInitiallyComposed = remember { mutableStateOf(false) }
|
||||
LaunchedEffect(key1 = true) {
|
||||
|
|
@ -32,7 +37,7 @@ internal fun TokenTextField(
|
|||
BasicTextField(
|
||||
value = state.value,
|
||||
onValueChange = state.onValueChange,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = keyboardType, imeAction = ImeAction.Default),
|
||||
keyboardOptions = keyboardOptions,
|
||||
singleLine = true,
|
||||
maxLines = 1,
|
||||
textStyle = TangemTheme.typography.subtitle1.copy(
|
||||
|
|
@ -42,6 +47,14 @@ internal fun TokenTextField(
|
|||
cursorBrush = SolidColor(TangemTheme.colors.icon.primary1),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onKeyEvent { keyEvent ->
|
||||
if (keyEvent.type == KeyEventType.KeyUp && keyEvent.key == Key.Enter) {
|
||||
onImeAction()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
.onFocusChanged {
|
||||
if (!it.isFocused && isInitiallyComposed.value) {
|
||||
state.onFocusExit()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameter
|
|||
import androidx.paging.LoadState
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.keyboardAsState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.managetokens.presentation.common.state.AlertState
|
||||
import com.tangem.managetokens.presentation.common.state.ChooseWalletState
|
||||
|
|
@ -46,6 +48,7 @@ internal fun ManageTokensScreen(state: ManageTokensState) {
|
|||
|
||||
@Composable
|
||||
private fun Content(state: ManageTokensState) {
|
||||
val keyboard by keyboardAsState()
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
|
@ -88,13 +91,17 @@ private fun Content(state: ManageTokensState) {
|
|||
|
||||
TokensList(tokens = tokens, addCustomTokenButton = state.addCustomTokenButton)
|
||||
}
|
||||
|
||||
state.derivationNotification?.let {
|
||||
DerivationNotification(
|
||||
config = it.config,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter),
|
||||
)
|
||||
if (keyboard is Keyboard.Closed) {
|
||||
DerivationNotification(
|
||||
config = it.config,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
state.selectedToken?.let { selectedToken ->
|
||||
ManageTokensBottomSheet(selectedToken = selectedToken, state = state)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue