Updated on 2026-08-14
This commit is contained in:
commit
078cf10f98
13 changed files with 169 additions and 85 deletions
|
|
@ -7,6 +7,8 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -68,6 +70,7 @@ fun PasteButton(
|
|||
enabled: Boolean = true,
|
||||
dpSize: DpSize = DpSize(40.dp, 40.dp),
|
||||
onClick: () -> Unit,
|
||||
tint: Color? = null,
|
||||
content: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
IconButton(
|
||||
|
|
@ -77,8 +80,42 @@ fun PasteButton(
|
|||
) {
|
||||
when (content) {
|
||||
null -> {
|
||||
val icon = if (enabled) R.drawable.ic_paste else R.drawable.ic_paste_disabled
|
||||
Icon(painterResource(id = icon), contentDescription = "Paste")
|
||||
val tintColor = tint
|
||||
?: colorResource(id = if (enabled) R.color.accent else R.color.accent_disabled)
|
||||
Icon(
|
||||
painterResource(id = R.drawable.ic_paste),
|
||||
contentDescription = "Paste",
|
||||
tint = tintColor,
|
||||
)
|
||||
}
|
||||
else -> content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ClearButton(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
dpSize: DpSize = DpSize(40.dp, 40.dp),
|
||||
onClick: () -> Unit,
|
||||
tint: Color? = null,
|
||||
content: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier.size(dpSize),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
) {
|
||||
when (content) {
|
||||
null -> {
|
||||
val tintColor = tint
|
||||
?: colorResource(id = if (enabled) R.color.accent else R.color.accent_disabled)
|
||||
Icon(
|
||||
painterResource(id = R.drawable.ic_clear),
|
||||
contentDescription = "Clear",
|
||||
tint = tintColor,
|
||||
)
|
||||
}
|
||||
else -> content()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.domain.common.util.ValueDebouncer
|
|||
@Composable
|
||||
fun <T> valueDebouncerAsState(
|
||||
initialValue: T,
|
||||
debounce: Long = 400,
|
||||
debounce: Long = 600,
|
||||
onEmitValueReceived: (T) -> Unit = {},
|
||||
onValueChanged: (T) -> Unit,
|
||||
): ValueDebouncer<T> {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ private fun OutlinedProgressTextField(
|
|||
onTextChanged: (String) -> Unit,
|
||||
) {
|
||||
val logger = remember {
|
||||
CompositionLogger(label, "OutlinedProgressTextField", listOf("Адрес контракта"))
|
||||
CompositionLogger(label, "OutlinedProgressTextField", listOf("Символ токена"))
|
||||
}
|
||||
logger.nextComposition()
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ private fun OutlinedProgressTextField(
|
|||
logger.log("$isNotUserInput: внешние данные ОДИНАКОВЫ с данными в поле")
|
||||
} else {
|
||||
logger.log("$isNotUserInput: внешние данные РАЗЛИЧАЮТСЯ с данными в поле")
|
||||
if (textDebouncer.emittedValue != textDebouncer.debounced) {
|
||||
if ((textDebouncer.emittedValue != textDebouncer.debounced) || textDebouncer.emitsCountBeforeDebounce > 0) {
|
||||
logger.log("$isNotUserInput: пользователь ВВОДИТ данные -> внешние данные игнорируем, ждем RECOMPOSE")
|
||||
} else {
|
||||
logger.log("$isNotUserInput: пользователь НЕ вводит данные -> пытаемся обработать внешние данные")
|
||||
|
|
@ -135,7 +135,7 @@ private fun OutlinedProgressTextField(
|
|||
textValueState.value = fieldData.value
|
||||
}
|
||||
} else {
|
||||
logger.log("$isNotUserInput: UNKNOWN -> start RECOMPOSE by new value for textValueState.value = [${fieldData.value}]")
|
||||
logger.log("$isNotUserInput: в пустое поле вставляются данные -> start RECOMPOSE новые данные для textValueState.value = [${fieldData.value}]")
|
||||
textValueState.value = fieldData.value
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,11 @@ private fun AddCustomTokenFab(
|
|||
} else {
|
||||
Color(0xFFB9E6D3)
|
||||
}
|
||||
val elevation = if (!isEnabled) {
|
||||
FloatingActionButtonDefaults.elevation(0.dp, 0.dp)
|
||||
} else {
|
||||
FloatingActionButtonDefaults.elevation()
|
||||
}
|
||||
|
||||
ToggledRippleTheme(isEnabled) {
|
||||
ExtendedFloatingActionButton(
|
||||
|
|
@ -156,6 +161,7 @@ private fun AddCustomTokenFab(
|
|||
onClick = { if (isEnabled) onClick() },
|
||||
backgroundColor = backgroundColor,
|
||||
contentColor = contentColor,
|
||||
elevation = elevation,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ package com.tangem.tap.features.tokens.addCustomToken.compose
|
|||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.domain.common.form.Field
|
||||
import com.tangem.domain.features.addCustomToken.TokenBlockchainField
|
||||
import com.tangem.domain.features.addCustomToken.TokenDerivationPathField
|
||||
import com.tangem.domain.features.addCustomToken.TokenField
|
||||
import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenAction
|
||||
import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenAction.*
|
||||
import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenState
|
||||
import com.tangem.domain.redux.domainStore
|
||||
import com.tangem.tap.common.compose.BlockchainSpinner
|
||||
import com.tangem.tap.common.compose.OutlinedTextFieldWidget
|
||||
import com.tangem.tap.common.compose.SpacerH8
|
||||
import com.tangem.tap.common.compose.TitleSubtitle
|
||||
import com.tangem.tap.common.compose.*
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
|
|
@ -34,12 +34,38 @@ fun TokenContractAddressView(screenFieldData: ScreenFieldData) {
|
|||
isLoading = screenFieldData.viewState.isLoading,
|
||||
error = screenFieldData.error,
|
||||
errorConverter = screenFieldData.errorConverter,
|
||||
// trailingIcon = { PasteClearButton(showFirst = tokenField.data.value.isEmpty()) }
|
||||
) {
|
||||
domainStore.dispatch(AddCustomTokenAction.OnTokenContractAddressChanged(Field.Data(it, true)))
|
||||
domainStore.dispatch(OnTokenContractAddressChanged(Field.Data(it, true)))
|
||||
}
|
||||
SpacerH8()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PasteClearButton(
|
||||
showFirst: Boolean,
|
||||
) {
|
||||
if (showFirst) {
|
||||
val context = LocalContext.current
|
||||
PasteButton(
|
||||
onClick = {
|
||||
context.getFromClipboard()?.let {
|
||||
val fieldData = Field.Data(it.toString(), false)
|
||||
domainStore.dispatch(OnTokenContractAddressChanged(fieldData))
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
} else {
|
||||
ClearButton(
|
||||
onClick = {
|
||||
val fieldData = Field.Data("", false)
|
||||
domainStore.dispatch(OnTokenContractAddressChanged(fieldData))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TokenNameView(screenFieldData: ScreenFieldData) {
|
||||
if (!screenFieldData.viewState.isVisible) return
|
||||
|
|
@ -54,7 +80,7 @@ fun TokenNameView(screenFieldData: ScreenFieldData) {
|
|||
error = screenFieldData.error,
|
||||
errorConverter = screenFieldData.errorConverter,
|
||||
) {
|
||||
domainStore.dispatch(AddCustomTokenAction.OnTokenNameChanged(Field.Data(it, true)))
|
||||
domainStore.dispatch(OnTokenNameChanged(Field.Data(it, true)))
|
||||
}
|
||||
SpacerH8()
|
||||
}
|
||||
|
|
@ -72,7 +98,7 @@ fun TokenNetworkView(screenFieldData: ScreenFieldData, state: AddCustomTokenStat
|
|||
selectedItem = networkField.data,
|
||||
isEnabled = screenFieldData.viewState.isEnabled,
|
||||
textFieldConverter = { state.blockchainToName(it) ?: notSelected },
|
||||
) { domainStore.dispatch(AddCustomTokenAction.OnTokenNetworkChanged(Field.Data(it, true))) }
|
||||
) { domainStore.dispatch(OnTokenNetworkChanged(Field.Data(it, true))) }
|
||||
SpacerH8()
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +115,7 @@ fun TokenSymbolView(screenFieldData: ScreenFieldData) {
|
|||
isEnabled = screenFieldData.viewState.isEnabled,
|
||||
error = screenFieldData.error,
|
||||
errorConverter = screenFieldData.errorConverter,
|
||||
) { domainStore.dispatch(AddCustomTokenAction.OnTokenSymbolChanged(Field.Data(it, true))) }
|
||||
) { domainStore.dispatch(OnTokenSymbolChanged(Field.Data(it, true))) }
|
||||
SpacerH8()
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +133,7 @@ fun TokenDecimalsView(screenFieldData: ScreenFieldData) {
|
|||
error = screenFieldData.error,
|
||||
errorConverter = screenFieldData.errorConverter,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
) { domainStore.dispatch(AddCustomTokenAction.OnTokenDecimalsChanged(Field.Data(it, true))) }
|
||||
) { domainStore.dispatch(OnTokenDecimalsChanged(Field.Data(it, true))) }
|
||||
SpacerH8()
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +155,12 @@ fun TokenDerivationPathView(screenFieldData: ScreenFieldData, state: AddCustomTo
|
|||
val blockchainName = state.blockchainToName(blockchain) ?: notSelected
|
||||
TitleSubtitle(derivationPathName, blockchainName)
|
||||
}
|
||||
) { domainStore.dispatch(AddCustomTokenAction.OnTokenDerivationPathChanged(Field.Data(it, true))) }
|
||||
) { domainStore.dispatch(OnTokenDerivationPathChanged(Field.Data(it, true))) }
|
||||
SpacerH8()
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TestTokenContractAddressView() {
|
||||
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ fun List<Currency>.filter(supportedBlockchains: Set<Blockchain>?): List<Currency
|
|||
it.copy(contracts =
|
||||
it.contracts.filter {
|
||||
supportedBlockchains.contains(it.blockchain) &&
|
||||
(it.blockchain.canHandleTokens() || it.blockchain.currency == it.address)
|
||||
(it.blockchain.canHandleTokens() || it.address == null)
|
||||
}
|
||||
)
|
||||
}.filterNot {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
|
|
@ -126,7 +127,7 @@ fun SaveChangesButton(keyboardState: Keyboard, onSaveChanges: () -> Unit) {
|
|||
)
|
||||
},
|
||||
onClick = onSaveChanges,
|
||||
backgroundColor = Color(0xFF1ACE80),
|
||||
backgroundColor = colorResource(id = R.color.accent),
|
||||
contentColor = Color.White,
|
||||
modifier = Modifier.padding(bottom = padding.dp)
|
||||
)
|
||||
|
|
|
|||
10
app/src/main/res/drawable/ic_clear.xml
Normal file
10
app/src/main/res/drawable/ic_clear.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#1C1C1E"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
||||
</vector>
|
||||
|
|
@ -4,6 +4,6 @@
|
|||
android:viewportWidth="16"
|
||||
android:viewportHeight="19">
|
||||
<path
|
||||
android:pathData="M13.8333,1.6667H10.35C10,0.7 9.0833,0 8,0C6.9167,0 6,0.7 5.65,1.6667H2.1667C1.25,1.6667 0.5,2.4167 0.5,3.3333V16.6667C0.5,17.5833 1.25,18.3333 2.1667,18.3333H13.8333C14.75,18.3333 15.5,17.5833 15.5,16.6667V3.3333C15.5,2.4167 14.75,1.6667 13.8333,1.6667ZM8,1.6667C8.4583,1.6667 8.8333,2.0417 8.8333,2.5C8.8333,2.9583 8.4583,3.3333 8,3.3333C7.5417,3.3333 7.1667,2.9583 7.1667,2.5C7.1667,2.0417 7.5417,1.6667 8,1.6667ZM13.8333,16.6667H2.1667V3.3333H3.8333V5.8333H12.1667V3.3333H13.8333V16.6667Z"
|
||||
android:fillColor="#1C1C1E"/>
|
||||
android:fillColor="#1C1C1E"
|
||||
android:pathData="M13.8333,1.6667H10.35C10,0.7 9.0833,0 8,0C6.9167,0 6,0.7 5.65,1.6667H2.1667C1.25,1.6667 0.5,2.4167 0.5,3.3333V16.6667C0.5,17.5833 1.25,18.3333 2.1667,18.3333H13.8333C14.75,18.3333 15.5,17.5833 15.5,16.6667V3.3333C15.5,2.4167 14.75,1.6667 13.8333,1.6667ZM8,1.6667C8.4583,1.6667 8.8333,2.0417 8.8333,2.5C8.8333,2.9583 8.4583,3.3333 8,3.3333C7.5417,3.3333 7.1667,2.9583 7.1667,2.5C7.1667,2.0417 7.5417,1.6667 8,1.6667ZM13.8333,16.6667H2.1667V3.3333H3.8333V5.8333H12.1667V3.3333H13.8333V16.6667Z" />
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -3,21 +3,23 @@
|
|||
|
||||
<color name="colorPrimary">#0029FF</color>
|
||||
<color name="colorSecondary">#0022D4</color>
|
||||
<color name="accent">#1ACE80</color>
|
||||
<color name="accent">#19C878</color>
|
||||
<color name="accent_disabled">#801ACE80</color>
|
||||
|
||||
<color name="toolbarColor">@color/backgroundLightGray</color>
|
||||
<color name="menu_accent_color">@color/accent</color>
|
||||
|
||||
<color name="tapButtonColor">@color/accent</color>
|
||||
<color name="tapButtonDisabled">#661ACE80</color>
|
||||
<color name="tapButtonDisabled">@color/accent_disabled</color>
|
||||
<color name="tapButtonColorBlack">@color/darkGray6</color>
|
||||
<color name="tapButtonBlackDisabled">#6A6A6A</color>
|
||||
|
||||
<color name="success">#5AC461</color>
|
||||
<color name="success">@color/accent</color>
|
||||
<color name="error">#C4291C</color>
|
||||
<color name="warning">#FFB71B</color>
|
||||
|
||||
<color name="white">#FFFFFF</color>
|
||||
<color name="toolbarColor">@color/backgroundLightGray</color>
|
||||
|
||||
<color name="white">#FFFFFF</color>
|
||||
<color name="lightGray0">#F3F3F3</color>
|
||||
<color name="lightGray1">#F8F8FB</color>
|
||||
<color name="lightGray2">#DADADF</color>
|
||||
|
|
@ -62,6 +64,4 @@
|
|||
<color name="warning_critical">#CA0F03</color>
|
||||
|
||||
<color name="gray_button">#EFEFF0</color>
|
||||
|
||||
<color name="menu_accent_color">#18C077</color>
|
||||
</resources>
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.domain.common.util
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -18,6 +18,8 @@ class ValueDebouncer<T>(
|
|||
|
||||
var emittedValue: T = initialValue
|
||||
private set
|
||||
var emitsCountBeforeDebounce: Int = 0
|
||||
private set
|
||||
var debounced: T = initialValue
|
||||
private set
|
||||
|
||||
|
|
@ -26,11 +28,14 @@ class ValueDebouncer<T>(
|
|||
|
||||
init {
|
||||
debounceScope.launch {
|
||||
flow.filter { if (debounced == null) true else debounced != it }
|
||||
.debounce(debounceDuration)
|
||||
flow.debounce(debounceDuration)
|
||||
.onEach {
|
||||
debounced = it
|
||||
onValueChanged(it)
|
||||
debounceScope.launch {
|
||||
delay(500)
|
||||
emitsCountBeforeDebounce = 0
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
}
|
||||
|
|
@ -39,6 +44,7 @@ class ValueDebouncer<T>(
|
|||
fun isDebounced(value: T): Boolean = this.debounced == value
|
||||
|
||||
fun emmit(emmitValue: T) {
|
||||
emitsCountBeforeDebounce++
|
||||
emittedValue = emmitValue
|
||||
onEmitValueReceived.invoke(emmitValue)
|
||||
debounceScope.launch { flow.emit(emmitValue) }
|
||||
|
|
|
|||
|
|
@ -59,48 +59,23 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
}
|
||||
is OnDestroy -> cancelAll()
|
||||
is OnTokenContractAddressChanged -> {
|
||||
val address = action.contractAddress.value
|
||||
val contractAddress = action.contractAddress.value
|
||||
|
||||
when (val error = ContractAddress.validateValue(address)) {
|
||||
null -> {
|
||||
// valid contract address
|
||||
ContractAddress.removeError()
|
||||
updateTokenDetailFields(false)
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
manageFoundTokenChanges(requestInfoAboutToken(address))
|
||||
}
|
||||
AddCustomTokenError.FieldIsEmpty -> {
|
||||
// empty contract address
|
||||
ContractAddress.removeError()
|
||||
clearTokenDetailsFields()
|
||||
updateTokenDetailFields(false)
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
AddCustomTokenError.InvalidContractAddress -> {
|
||||
ContractAddress.addError(error)
|
||||
updateTokenDetailFields(hubState.tokensAnyFieldsIsFilled())
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
}
|
||||
validateContractAddressAndNotify(contractAddress)
|
||||
}
|
||||
is OnTokenNetworkChanged -> {
|
||||
if (!action.blockchainNetwork.isUserInput) return
|
||||
|
||||
val contractAddress = ContractAddress.getFieldValue<String>()
|
||||
val error = ContractAddress.validateValue(contractAddress)
|
||||
if (error == null && contractAddress.isNotEmpty()) {
|
||||
// token branch
|
||||
manageFoundTokenChanges(requestInfoAboutToken(contractAddress))
|
||||
} else {
|
||||
// blockchain branch
|
||||
val isAlreadyAdded = isBlockchainPersistIntoAppSavedTokensList(
|
||||
selectedNetwork = action.blockchainNetwork.value
|
||||
)
|
||||
updateWarningAlreadyAdded(isAlreadyAdded)
|
||||
checkAndUpdateAddButton()
|
||||
when (validateContractAddressAndNotify(contractAddress)) {
|
||||
is AddCustomTokenError.InvalidContractAddress -> {
|
||||
val isAlreadyAdded = isBlockchainPersistIntoAppSavedTokensList(
|
||||
selectedNetwork = action.blockchainNetwork.value
|
||||
)
|
||||
updateWarningAlreadyAdded(isAlreadyAdded)
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
is OnTokenDerivationPathChanged -> {
|
||||
|
|
@ -118,19 +93,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
updateWarningAlreadyAdded(isAlreadyAdded)
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
is OnTokenNameChanged -> {
|
||||
// changeBlockchainNetworkList()
|
||||
// updateTokenDetailFields(hubState.tokensAnyFieldsIsFilled())
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
is OnTokenSymbolChanged -> {
|
||||
// changeBlockchainNetworkList()
|
||||
// updateTokenDetailFields(hubState.tokensAnyFieldsIsFilled())
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
is OnTokenDecimalsChanged -> {
|
||||
// changeBlockchainNetworkList()
|
||||
// updateTokenDetailFields(hubState.tokensAnyFieldsIsFilled())
|
||||
is OnTokenNameChanged, is OnTokenSymbolChanged, is OnTokenDecimalsChanged -> {
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
is OnAddCustomTokenClicked -> {
|
||||
|
|
@ -157,6 +120,35 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun validateContractAddressAndNotify(contractAddress: String): AddCustomTokenError? {
|
||||
val error = ContractAddress.validateValue(contractAddress)
|
||||
when (error) {
|
||||
null -> {
|
||||
// valid contract address
|
||||
ContractAddress.removeError()
|
||||
updateTokenDetailFields(false)
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
manageFoundTokenChanges(requestInfoAboutToken(contractAddress))
|
||||
}
|
||||
AddCustomTokenError.FieldIsEmpty -> {
|
||||
// empty contract address
|
||||
ContractAddress.removeError()
|
||||
clearTokenDetailsFields()
|
||||
updateTokenDetailFields(false)
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
AddCustomTokenError.InvalidContractAddress -> {
|
||||
ContractAddress.addError(error)
|
||||
updateTokenDetailFields(hubState.tokensAnyFieldsIsFilled())
|
||||
changeBlockchainNetworkList()
|
||||
checkAndUpdateAddButton()
|
||||
}
|
||||
}
|
||||
return error
|
||||
}
|
||||
|
||||
/**
|
||||
* This feature is only needed until Solana coins are added.
|
||||
* While they are not there - this function excludes the Solana blockchain if the user has
|
||||
|
|
|
|||
|
|
@ -172,10 +172,10 @@ data class AddCustomTokenState(
|
|||
Blockchain.Unknown,
|
||||
Blockchain.Ethereum,
|
||||
Blockchain.BSC,
|
||||
Blockchain.Binance, // not evm
|
||||
Blockchain.Polygon,
|
||||
Blockchain.Avalanche,
|
||||
Blockchain.Fantom,
|
||||
Blockchain.Binance, // not evm
|
||||
Blockchain.Solana, // not evm. Should be unsupported for coins until they are added to the Blockchain SDK
|
||||
)
|
||||
if (type == CustomTokenType.Token) networks.remove(Blockchain.Solana)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue