Updated on 2026-08-14
This commit is contained in:
parent
81777ad79e
commit
a223c140cf
17 changed files with 890 additions and 24 deletions
|
|
@ -45,7 +45,9 @@ internal fun ChooseWalletScreen(state: ChooseWalletState.Choose, modifier: Modif
|
|||
) {
|
||||
IconButton(
|
||||
onClick = state.onCloseChoosingWalletClick,
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.clickable { state.onCloseChoosingWalletClick() },
|
||||
) {
|
||||
Icon(
|
||||
painterResource(id = R.drawable.ic_back_24),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.state.previewdata
|
||||
|
||||
import com.tangem.managetokens.presentation.common.state.ChooseWalletState
|
||||
import com.tangem.managetokens.presentation.common.state.WalletState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.*
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
|
||||
internal object AddCustomTokenPreviewData {
|
||||
val state = AddCustomTokenState(
|
||||
chooseWalletState = ChooseWalletState.Choose(
|
||||
wallets = persistentListOf(),
|
||||
selectedWallet = WalletState(
|
||||
"",
|
||||
"",
|
||||
"My Wallet",
|
||||
{},
|
||||
),
|
||||
onChooseWalletClick = { },
|
||||
onCloseChoosingWalletClick = { },
|
||||
),
|
||||
chooseNetworkState = ChooseNetworkState(
|
||||
networks = persistentListOf(),
|
||||
selectedNetwork = null,
|
||||
onChooseNetworkClick = { },
|
||||
onCloseChoosingNetworkClick = {},
|
||||
),
|
||||
chooseDerivationState = ChooseDerivationState(
|
||||
derivations = persistentListOf(),
|
||||
selectedDerivation = null,
|
||||
enterCustomDerivationState = null,
|
||||
onChooseDerivationClick = { },
|
||||
onCloseChoosingDerivationClick = {},
|
||||
onEnterCustomDerivation = {},
|
||||
),
|
||||
tokenData = CustomTokenData(
|
||||
contractAddressTextField = TextFieldState.Editable(
|
||||
value = "0x4ace7262705b68bcba5b91de96889349394",
|
||||
isEnabled = false,
|
||||
onValueChange = {},
|
||||
),
|
||||
nameTextField = TextFieldState.Loading,
|
||||
symbolTextField = TextFieldState.Loading,
|
||||
decimalsTextField = TextFieldState.Loading,
|
||||
),
|
||||
warnings = persistentSetOf(),
|
||||
addTokenButton = ButtonState(isEnabled = true, onClick = {}),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.state.previewdata
|
||||
|
||||
import com.tangem.managetokens.presentation.customtokens.state.ChooseDerivationState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.Derivation
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object ChooseDerivationPreviewData {
|
||||
private val derivations: ImmutableList<Derivation> = persistentListOf(
|
||||
Derivation(
|
||||
networkName = "Ethereum",
|
||||
path = "m/44’/9001’/0’/0/0",
|
||||
networkId = "ethereum",
|
||||
standardType = "ERC",
|
||||
onDerivationSelected = {},
|
||||
),
|
||||
Derivation(
|
||||
networkName = "Polygon",
|
||||
path = "m/44’/9001’/0’/0/0",
|
||||
networkId = "polygon",
|
||||
standardType = "ERC",
|
||||
onDerivationSelected = {},
|
||||
),
|
||||
Derivation(
|
||||
networkName = "Avalanche",
|
||||
path = "m/44’/9001’/0’/0/0",
|
||||
networkId = "avalanche",
|
||||
standardType = "ERC",
|
||||
onDerivationSelected = {},
|
||||
),
|
||||
)
|
||||
|
||||
val state = ChooseDerivationState(
|
||||
derivations = derivations,
|
||||
selectedDerivation = derivations.first(),
|
||||
enterCustomDerivationState = null,
|
||||
onEnterCustomDerivation = {},
|
||||
onCloseChoosingDerivationClick = {},
|
||||
onChooseDerivationClick = {},
|
||||
show = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.state.previewdata
|
||||
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.common.state.NetworkItemState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.ChooseNetworkState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object ChooseNetworkCustomPreviewData {
|
||||
val networks = persistentListOf(
|
||||
NetworkItemState.Selectable(
|
||||
name = "Ethereum",
|
||||
protocolName = "ETH",
|
||||
iconResId = R.drawable.img_kusama_22,
|
||||
id = "ethereum",
|
||||
onNetworkClick = { },
|
||||
),
|
||||
NetworkItemState.Selectable(
|
||||
name = "BNB SMART CHAIN",
|
||||
protocolName = "BEP20",
|
||||
iconResId = R.drawable.ic_bsc_16,
|
||||
id = "binance smart chain",
|
||||
onNetworkClick = { },
|
||||
),
|
||||
)
|
||||
val state = ChooseNetworkState(
|
||||
networks,
|
||||
selectedNetwork = networks.first(),
|
||||
onCloseChoosingNetworkClick = {},
|
||||
onChooseNetworkClick = {},
|
||||
show = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.common.ui.components.SimpleSelectionBlock
|
||||
import com.tangem.managetokens.presentation.customtokens.state.ChooseDerivationState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.previewdata.ChooseDerivationPreviewData
|
||||
|
||||
@Composable
|
||||
internal fun ChooseDerivationScreen(state: ChooseDerivationState, modifier: Modifier = Modifier) {
|
||||
if (state.enterCustomDerivationState != null) {
|
||||
CustomDerivationDialog(state.enterCustomDerivationState)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding()
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing10,
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing18,
|
||||
),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size44)
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_back_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
modifier = Modifier
|
||||
.clickable { state.onCloseChoosingDerivationClick() },
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.custom_token_derivation_path),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing24)
|
||||
.align(Alignment.Center),
|
||||
)
|
||||
}
|
||||
DerivationsList(state)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DerivationsList(state: ChooseDerivationState) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
contentPadding = PaddingValues(vertical = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
item {
|
||||
SimpleSelectionBlock(
|
||||
title = stringResource(id = R.string.custom_token_custom_derivation),
|
||||
subtitle = stringResource(id = R.string.custom_token_custom_derivation),
|
||||
onClick = state.onEnterCustomDerivation,
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
items(state.derivations.count()) { index ->
|
||||
val derivationItem = state.derivations[index]
|
||||
SimpleSelectionBlock(
|
||||
title = derivationItem.networkName,
|
||||
subtitle = derivationItem.path,
|
||||
onClick = { derivationItem.onDerivationSelected(derivationItem) },
|
||||
modifier = Modifier.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = state.derivations.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
),
|
||||
roundedCorners = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseDerivationScreen_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
ChooseDerivationScreen(state = ChooseDerivationPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseDerivationScreen_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
ChooseDerivationScreen(state = ChooseDerivationPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.common.ui.components.NetworkItem
|
||||
import com.tangem.managetokens.presentation.customtokens.state.ChooseNetworkState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.previewdata.ChooseNetworkCustomPreviewData
|
||||
|
||||
@Composable
|
||||
internal fun ChooseNetworkCustomScreen(state: ChooseNetworkState, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding()
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing10,
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing18,
|
||||
),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size44)
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_back_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
modifier = Modifier
|
||||
.clickable { state.onCloseChoosingNetworkClick() },
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.custom_token_network_selector_title),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing24)
|
||||
.align(Alignment.Center),
|
||||
)
|
||||
}
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
items(state.networks.count()) { index ->
|
||||
NetworkItem(
|
||||
state = state.networks[index],
|
||||
tokenState = null,
|
||||
isSelected = state.selectedNetwork == state.networks[index],
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = state.networks.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseNetworkScreen_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
ChooseNetworkCustomScreen(ChooseNetworkCustomPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseNetworkScreen_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
ChooseNetworkCustomScreen(ChooseNetworkCustomPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.ui.components.AdditionalTextInputDialogParams
|
||||
import com.tangem.core.ui.components.DialogButton
|
||||
import com.tangem.core.ui.components.TextInputDialog
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.customtokens.state.EnterCustomDerivationState
|
||||
|
||||
@Composable
|
||||
internal fun CustomDerivationDialog(state: EnterCustomDerivationState) {
|
||||
val confirmButton = DialogButton(
|
||||
title = stringResource(id = R.string.common_ok),
|
||||
enabled = state.confirmButtonEnabled,
|
||||
onClick = state.onConfirmButtonClick,
|
||||
)
|
||||
|
||||
val dismissButton = DialogButton(
|
||||
title = stringResource(id = R.string.common_cancel),
|
||||
onClick = state.onDismiss,
|
||||
)
|
||||
|
||||
val params = AdditionalTextInputDialogParams(
|
||||
placeholder = stringResource(id = R.string.custom_token_custom_derivation_placeholder),
|
||||
isError = state.derivationIncorrect,
|
||||
errorText = if (state.derivationIncorrect) {
|
||||
stringResource(R.string.custom_token_invalid_derivation_path)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
|
||||
TextInputDialog(
|
||||
fieldValue = state.value,
|
||||
confirmButton = confirmButton,
|
||||
onDismissDialog = state.onDismiss,
|
||||
onValueChange = state.onValueChange,
|
||||
textFieldParams = params,
|
||||
title = stringResource(id = R.string.custom_token_custom_derivation_title),
|
||||
dismissButton = dismissButton,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.managetokens.presentation.common.state.ChooseWalletState
|
||||
import com.tangem.managetokens.presentation.common.ui.ChooseWalletScreen
|
||||
|
||||
@Composable
|
||||
internal fun CustomTokensChooseWalletScreen(state: ChooseWalletState.Choose) {
|
||||
ChooseWalletScreen(
|
||||
state = state,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding(),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
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.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.common.state.AlertState
|
||||
import com.tangem.managetokens.presentation.common.state.ChooseWalletState
|
||||
import com.tangem.managetokens.presentation.common.ui.ChooseWalletBottomSheet
|
||||
import com.tangem.managetokens.presentation.common.ui.ChooseWalletBottomSheetConfig
|
||||
import com.tangem.managetokens.presentation.common.ui.EventEffect
|
||||
import com.tangem.managetokens.presentation.common.ui.components.Alert
|
||||
import com.tangem.managetokens.presentation.common.ui.components.SimpleSelectionBlock
|
||||
import com.tangem.managetokens.presentation.customtokens.state.AddCustomTokenState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.CustomTokenData
|
||||
import com.tangem.managetokens.presentation.customtokens.state.TextFieldState
|
||||
import com.tangem.managetokens.presentation.customtokens.state.previewdata.AddCustomTokenPreviewData
|
||||
|
||||
@Composable
|
||||
internal fun CustomTokensScreen(state: AddCustomTokenState, modifier: Modifier = Modifier) {
|
||||
var alertState by remember { mutableStateOf<AlertState?>(value = null) }
|
||||
|
||||
EventEffect(
|
||||
event = state.event,
|
||||
onAlertStateSet = { alertState = it },
|
||||
)
|
||||
alertState?.let {
|
||||
Alert(state = it, onDismiss = { alertState = null })
|
||||
}
|
||||
Content(state = state, modifier = modifier)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(state: AddCustomTokenState, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding()
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing10,
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing18,
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.manage_tokens_network_selector_title),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = TangemTheme.dimens.spacing10),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.custom_token_subtitle),
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
CustomTokenItemsList(state = state)
|
||||
PrimaryButton(
|
||||
text = stringResource(id = R.string.custom_token_add_token),
|
||||
onClick = state.addTokenButton.onClick,
|
||||
enabled = state.addTokenButton.isEnabled,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
||||
if (state.chooseWalletState is ChooseWalletState.Choose && state.chooseWalletState.show) {
|
||||
val config = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
content = ChooseWalletBottomSheetConfig(state.chooseWalletState),
|
||||
onDismissRequest = state.chooseWalletState.onCloseChoosingWalletClick,
|
||||
)
|
||||
ChooseWalletBottomSheet(config)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.CustomTokenItemsList(state: AddCustomTokenState, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
) {
|
||||
if (state.chooseWalletState is ChooseWalletState.Choose) {
|
||||
item {
|
||||
SimpleSelectionBlock(
|
||||
title = stringResource(id = R.string.manage_tokens_network_selector_wallet),
|
||||
subtitle = state.chooseWalletState.selectedWallet?.walletName ?: "",
|
||||
onClick = state.chooseWalletState.onChooseWalletClick,
|
||||
modifier = Modifier
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
SimpleSelectionBlock(
|
||||
title = stringResource(id = R.string.custom_token_network_input_title),
|
||||
subtitle = state.chooseNetworkState.selectedNetwork?.name
|
||||
?: stringResource(id = R.string.manage_tokens_network_selector_title),
|
||||
onClick = state.chooseNetworkState.onChooseNetworkClick,
|
||||
modifier = Modifier
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
if (state.tokenData != null) {
|
||||
item {
|
||||
TokenFields(
|
||||
state = state.tokenData,
|
||||
modifier = Modifier
|
||||
.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (state.chooseDerivationState != null) {
|
||||
item {
|
||||
SimpleSelectionBlock(
|
||||
title = stringResource(id = R.string.custom_token_derivation_path),
|
||||
subtitle = state.chooseDerivationState.selectedDerivation?.path
|
||||
?: stringResource(id = R.string.custom_token_derivation_path_default),
|
||||
onClick = state.chooseDerivationState.onChooseDerivationClick,
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenFields(state: CustomTokenData, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(shape = RoundedCornerShape(TangemTheme.dimens.radius16))
|
||||
.background(color = TangemTheme.colors.background.action),
|
||||
) {
|
||||
TokenField(
|
||||
textFieldState = state.contractAddressTextField,
|
||||
placeholder = "0x0000000000000000000000000000000",
|
||||
title = R.string.custom_token_contract_address_input_title,
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.nameTextField,
|
||||
placeholder = stringResource(id = R.string.custom_token_name_input_placeholder),
|
||||
title = R.string.custom_token_name_input_title,
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.symbolTextField,
|
||||
placeholder = stringResource(id = R.string.custom_token_token_symbol_input_placeholder),
|
||||
title = R.string.custom_token_token_symbol_input_title,
|
||||
)
|
||||
TokenField(
|
||||
textFieldState = state.decimalsTextField,
|
||||
placeholder = "0",
|
||||
title = R.string.custom_token_decimals_input_title,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenField(
|
||||
textFieldState: TextFieldState,
|
||||
placeholder: String,
|
||||
title: Int,
|
||||
keyboardType: KeyboardType = KeyboardType.Text,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(color = TangemTheme.colors.background.action)
|
||||
.padding(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
TokenTextFieldTitle(
|
||||
state = textFieldState,
|
||||
title = stringResource(id = title),
|
||||
)
|
||||
when (textFieldState) {
|
||||
is TextFieldState.Editable -> TokenTextField(
|
||||
state = textFieldState,
|
||||
placeholder = placeholder,
|
||||
keyboardType = keyboardType,
|
||||
)
|
||||
is TextFieldState.Loading -> TokenShimmer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenShimmer() {
|
||||
RectangleShimmer(
|
||||
radius = TangemTheme.dimens.radius3,
|
||||
modifier = Modifier
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
.size(
|
||||
height = TangemTheme.dimens.size12,
|
||||
width = TangemTheme.dimens.size90,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenTextFieldTitle(state: TextFieldState?, title: String) {
|
||||
val modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing4)
|
||||
val error = (state as? TextFieldState.Editable)?.error
|
||||
if (error == null) {
|
||||
Text(
|
||||
text = title,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = error.title.resolveReference(),
|
||||
color = TangemTheme.colors.text.warning,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseDerivationScreen_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
CustomTokensScreen(state = AddCustomTokenPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ChooseDerivationScreen_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
CustomTokensScreen(state = AddCustomTokenPreviewData.state)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.managetokens.presentation.customtokens.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.managetokens.presentation.customtokens.state.TextFieldState
|
||||
|
||||
@Composable
|
||||
internal fun TokenTextField(
|
||||
state: TextFieldState.Editable,
|
||||
placeholder: String,
|
||||
keyboardType: KeyboardType = KeyboardType.Text,
|
||||
) {
|
||||
BasicTextField(
|
||||
value = state.value,
|
||||
onValueChange = state.onValueChange,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = keyboardType, imeAction = ImeAction.Default),
|
||||
singleLine = true,
|
||||
maxLines = 1,
|
||||
textStyle = TangemTheme.typography.subtitle1.copy(
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = if (state.isEnabled) TangemTheme.colors.text.primary1 else TangemTheme.colors.text.disabled,
|
||||
),
|
||||
cursorBrush = SolidColor(TangemTheme.colors.icon.primary1),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
decorationBox = { innerTextField ->
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
if (state.value.isEmpty()) {
|
||||
Text(
|
||||
text = placeholder,
|
||||
color = if (state.isEnabled) {
|
||||
TangemTheme.colors.text.tertiary
|
||||
} else {
|
||||
TangemTheme.colors.text.disabled
|
||||
},
|
||||
style = TangemTheme.typography.body2,
|
||||
)
|
||||
}
|
||||
}
|
||||
innerTextField()
|
||||
},
|
||||
enabled = state.isEnabled,
|
||||
)
|
||||
}
|
||||
|
|
@ -14,6 +14,11 @@ import com.tangem.core.navigation.AppScreen
|
|||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.navigation.ReduxNavController
|
||||
import com.tangem.managetokens.ManageTokensFragment
|
||||
import com.tangem.managetokens.presentation.common.state.ChooseWalletState
|
||||
import com.tangem.managetokens.presentation.customtokens.ui.ChooseDerivationScreen
|
||||
import com.tangem.managetokens.presentation.customtokens.ui.ChooseNetworkCustomScreen
|
||||
import com.tangem.managetokens.presentation.customtokens.ui.CustomTokensChooseWalletScreen
|
||||
import com.tangem.managetokens.presentation.customtokens.ui.CustomTokensScreen
|
||||
import com.tangem.managetokens.presentation.customtokens.viewmodels.CustomTokensViewModel
|
||||
import com.tangem.managetokens.presentation.managetokens.ui.ManageTokensScreen
|
||||
import com.tangem.managetokens.presentation.managetokens.viewmodels.ManageTokensViewModel
|
||||
|
|
@ -50,8 +55,7 @@ internal class DefaultManageTokensRouter(
|
|||
val viewModel = hiltViewModel<CustomTokensViewModel>(viewModelStoreOwner).apply {
|
||||
router = this@DefaultManageTokensRouter
|
||||
}
|
||||
// CustomTokensScreen(state = viewModel.uiState)
|
||||
// TODO: enable in [REDACTED_JIRA]
|
||||
CustomTokensScreen(state = viewModel.uiState)
|
||||
}
|
||||
composable(
|
||||
ManageTokensRoute.CustomTokens.ChooseNetwork.route,
|
||||
|
|
@ -59,10 +63,9 @@ internal class DefaultManageTokensRouter(
|
|||
val viewModel = hiltViewModel<CustomTokensViewModel>(viewModelStoreOwner).apply {
|
||||
router = this@DefaultManageTokensRouter
|
||||
}
|
||||
// ChooseNetworkCustomScreen(
|
||||
// state = viewModel.uiState.chooseNetworkState,
|
||||
// )
|
||||
// TODO: enable in [REDACTED_JIRA]
|
||||
ChooseNetworkCustomScreen(
|
||||
state = viewModel.uiState.chooseNetworkState,
|
||||
)
|
||||
}
|
||||
composable(
|
||||
ManageTokensRoute.CustomTokens.ChooseDerivation.route,
|
||||
|
|
@ -70,10 +73,9 @@ internal class DefaultManageTokensRouter(
|
|||
val viewModel = hiltViewModel<CustomTokensViewModel>(viewModelStoreOwner).apply {
|
||||
router = this@DefaultManageTokensRouter
|
||||
}
|
||||
// ChooseDerivationScreen(
|
||||
// state = requireNotNull(viewModel.uiState.chooseDerivationState),
|
||||
// )
|
||||
// TODO: enable in [REDACTED_JIRA]
|
||||
ChooseDerivationScreen(
|
||||
state = requireNotNull(viewModel.uiState.chooseDerivationState),
|
||||
)
|
||||
}
|
||||
composable(
|
||||
ManageTokensRoute.CustomTokens.ChooseWallet.route,
|
||||
|
|
@ -81,10 +83,9 @@ internal class DefaultManageTokensRouter(
|
|||
val viewModel = hiltViewModel<CustomTokensViewModel>(viewModelStoreOwner).apply {
|
||||
router = this@DefaultManageTokensRouter
|
||||
}
|
||||
// CustomTokensChooseWalletScreen(
|
||||
// state = viewModel.uiState.chooseWalletState as ChooseWalletState.Choose,
|
||||
// )
|
||||
// TODO: enable in [REDACTED_JIRA]
|
||||
CustomTokensChooseWalletScreen(
|
||||
state = viewModel.uiState.chooseWalletState as ChooseWalletState.Choose,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue