Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-30 12:13:05 +04:00
commit e270d885dc
6 changed files with 177 additions and 44 deletions

View file

@ -9,6 +9,7 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import com.tangem.core.ui.R
@ -32,12 +33,13 @@ fun InformationBlock(
title: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentHorizontalPadding: Dp = TangemTheme.dimens.spacing12,
shape: Shape = TangemTheme.shapes.roundedCornersXMedium,
action: (@Composable BoxScope.() -> Unit)? = null,
content: (@Composable InformationBlockContentScope.() -> Unit)? = null,
) {
Column(
modifier = modifier
.clip(TangemTheme.shapes.roundedCornersXMedium)
.clip(shape)
.background(color = TangemTheme.colors.background.action),
horizontalAlignment = Alignment.Start,
) {

View file

@ -0,0 +1,16 @@
package com.tangem.features.managetokens.component
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableDialogComponent
import com.tangem.domain.wallets.models.UserWalletId
internal interface CustomTokenDerivationInputComponent : ComposableDialogComponent {
data class Params(
val userWalletId: UserWalletId,
val onConfirm: (String) -> Unit,
val onDismiss: () -> Unit,
)
interface Factory : ComponentFactory<Params, CustomTokenDerivationInputComponent>
}

View file

@ -0,0 +1,34 @@
package com.tangem.features.managetokens.component.preview
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.extensions.stringReference
import com.tangem.features.managetokens.component.CustomTokenDerivationInputComponent
import com.tangem.features.managetokens.entity.customtoken.CustomDerivationInputUM
import com.tangem.features.managetokens.ui.dialog.CustomDerivationInputDialog
internal class PreviewCustomTokenDerivationInputComponent(
private val value: String = "",
private val error: String? = null,
) : CustomTokenDerivationInputComponent {
override fun dismiss() {
/* no-op */
}
@Composable
override fun Dialog() {
val model = CustomDerivationInputUM(
value = TextFieldValue(value),
error = error?.let(::stringReference),
updateValue = {},
isConfirmEnabled = false,
onConfirm = {},
)
CustomDerivationInputDialog(
model = model,
onDismiss = ::dismiss,
)
}
}

View file

@ -0,0 +1,12 @@
package com.tangem.features.managetokens.entity.customtoken
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.extensions.TextReference
internal data class CustomDerivationInputUM(
val value: TextFieldValue,
val error: TextReference? = null,
val updateValue: (value: TextFieldValue) -> Unit,
val isConfirmEnabled: Boolean,
val onConfirm: () -> Unit,
)

View file

@ -21,6 +21,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.block.information.InformationBlock
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.rows.ChainRow
import com.tangem.core.ui.components.rows.model.ChainRowUM
@ -34,7 +35,6 @@ import com.tangem.features.managetokens.component.CustomTokenSelectorComponent
import com.tangem.features.managetokens.component.preview.PreviewCustomTokenSelectorComponent
import com.tangem.features.managetokens.entity.customtoken.CustomTokenSelectorUM
import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath
import com.tangem.features.managetokens.entity.customtoken.SelectedNetwork
import com.tangem.features.managetokens.entity.item.CurrencyNetworkUM
import com.tangem.features.managetokens.entity.item.DerivationPathUM
import com.tangem.features.managetokens.impl.R
@ -46,7 +46,9 @@ internal fun CustomTokenSelectorContent(model: CustomTokenSelectorUM, modifier:
val lastIndex = model.items.lastIndex
LazyColumn(
modifier = modifier,
modifier = modifier.background(
color = TangemTheme.colors.background.secondary,
),
contentPadding = PaddingValues(
bottom = TangemTheme.dimens.spacing16 + bottomBarHeight,
),
@ -178,38 +180,47 @@ private fun NetworkItem(model: CurrencyNetworkUM, modifier: Modifier = Modifier)
@Composable
private fun CustomDerivationButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
// TODO: Implement in [REDACTED_JIRA]
Box(
modifier = modifier
.fillMaxWidth()
.heightIn(min = TangemTheme.dimens.size56)
.clip(shape = TangemTheme.shapes.roundedCornersXMedium)
.background(color = TangemTheme.colors.background.primary)
.clickable(onClick = onClick)
.padding(all = TangemTheme.dimens.spacing12),
contentAlignment = Alignment.CenterStart,
) {
Text(
text = "Custom",
color = TangemTheme.colors.text.primary1,
)
}
InformationBlock(
modifier = modifier.clickable(onClick = onClick),
title = {
Text(
text = stringResource(id = R.string.custom_token_custom_derivation),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
)
},
content = {
Text(
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
text = stringResource(id = R.string.custom_token_custom_derivation_title),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
)
},
)
}
@Composable
private fun DerivationPathItem(model: DerivationPathUM, modifier: Modifier = Modifier) {
// TODO: Implement in [REDACTED_JIRA]
Box(
modifier = modifier
.heightIn(TangemTheme.dimens.size56)
.padding(all = TangemTheme.dimens.spacing12),
contentAlignment = Alignment.CenterStart,
) {
Text(
text = "${model.networkName.resolveReference()}: ${model.value} ${if (model.isSelected) "<" else ""}",
color = TangemTheme.colors.text.primary1,
)
}
InformationBlock(
modifier = modifier,
shape = RectangleShape,
title = {
Text(
text = model.networkName.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
)
},
content = {
Text(
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
text = model.value,
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
)
},
)
}
// region Preview
@ -229,19 +240,6 @@ private class CustomTokenNetworkSelectorComponentPreviewProvider :
PreviewParameterProvider<CustomTokenSelectorComponent> {
override val values: Sequence<CustomTokenSelectorComponent>
get() = sequenceOf(
PreviewCustomTokenSelectorComponent(),
PreviewCustomTokenSelectorComponent(
params = CustomTokenSelectorComponent.Params.NetworkSelector(
userWalletId = UserWalletId(stringValue = "321"),
selectedNetwork = SelectedNetwork(
id = Network.ID(value = "0"),
name = stringReference(""),
derivationPath = Network.DerivationPath.Card("m/44'/0'/0'/0/0"),
canHandleTokens = false,
),
onNetworkSelected = {},
),
),
PreviewCustomTokenSelectorComponent(
params = CustomTokenSelectorComponent.Params.DerivationPathSelector(
userWalletId = UserWalletId(stringValue = "321"),

View file

@ -0,0 +1,71 @@
package com.tangem.features.managetokens.ui.dialog
import android.content.res.Configuration
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.AdditionalTextInputDialogUM
import com.tangem.core.ui.components.DialogButtonUM
import com.tangem.core.ui.components.TextInputDialog
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.managetokens.component.CustomTokenDerivationInputComponent
import com.tangem.features.managetokens.component.preview.PreviewCustomTokenDerivationInputComponent
import com.tangem.features.managetokens.entity.customtoken.CustomDerivationInputUM
import com.tangem.features.managetokens.impl.R
@Composable
internal fun CustomDerivationInputDialog(model: CustomDerivationInputUM, onDismiss: () -> Unit) {
val value by rememberUpdatedState(newValue = model.value)
TextInputDialog(
title = stringResource(id = R.string.custom_token_custom_derivation_title),
fieldValue = value,
confirmButton = DialogButtonUM(
title = stringResource(id = R.string.common_ok),
enabled = model.isConfirmEnabled,
onClick = model.onConfirm,
),
dismissButton = DialogButtonUM(
title = stringResource(id = R.string.common_cancel),
onClick = onDismiss,
),
onDismissDialog = onDismiss,
onValueChange = model.updateValue,
textFieldParams = AdditionalTextInputDialogUM(
label = model.error?.resolveReference() ?: stringResource(id = R.string.custom_token_derivation_path),
isError = model.error != null,
),
)
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_CustomDerivationInputDialog(
@PreviewParameter(ComponentPreviewProvider::class) component: CustomTokenDerivationInputComponent,
) {
TangemThemePreview {
component.Dialog()
}
}
private class ComponentPreviewProvider : PreviewParameterProvider<CustomTokenDerivationInputComponent> {
override val values: Sequence<CustomTokenDerivationInputComponent>
get() = sequenceOf(
PreviewCustomTokenDerivationInputComponent(),
PreviewCustomTokenDerivationInputComponent(
value = "m/44'/60'/0'/0/0",
),
PreviewCustomTokenDerivationInputComponent(
value = "m/44'/60'/0'/0/0",
error = "Invalid derivation path",
),
)
}
// endregion Preview