Updated on 2026-08-14
This commit is contained in:
commit
f71fe3aa6b
27 changed files with 331 additions and 120 deletions
|
|
@ -324,6 +324,7 @@ internal class DefaultWalletConnectRepository(
|
|||
optionalNamespace.key to Wallet.Model.Namespace.Session(
|
||||
accounts = accountsOptional.distinct(),
|
||||
methods = methods,
|
||||
chains = userChains.keys.toList(),
|
||||
events = optionalNamespace.value.events,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package com.tangem.core.ui.components.atoms.text
|
|||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -12,22 +12,19 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.layout.SubcomposeLayout
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
sealed class TextEllipsis {
|
||||
|
||||
object Middle : TextEllipsis()
|
||||
data object Middle : TextEllipsis()
|
||||
|
||||
object End : TextEllipsis()
|
||||
|
||||
|
|
@ -50,14 +47,9 @@ fun EllipsisText(
|
|||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color.Unspecified,
|
||||
fontSize: TextUnit = TextUnit.Unspecified,
|
||||
fontStyle: FontStyle? = null,
|
||||
fontWeight: FontWeight? = null,
|
||||
fontFamily: FontFamily? = null,
|
||||
letterSpacing: TextUnit = TextUnit.Unspecified,
|
||||
textDecoration: TextDecoration? = null,
|
||||
textAlign: TextAlign? = null,
|
||||
lineHeight: TextUnit = TextUnit.Unspecified,
|
||||
softWrap: Boolean = true,
|
||||
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||
style: TextStyle = LocalTextStyle.current,
|
||||
|
|
@ -83,18 +75,14 @@ fun EllipsisText(
|
|||
Text(
|
||||
text = layoutText,
|
||||
color = color,
|
||||
fontSize = fontSize,
|
||||
style = style,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = fontWeight,
|
||||
fontFamily = fontFamily,
|
||||
letterSpacing = letterSpacing,
|
||||
textDecoration = textDecoration,
|
||||
textAlign = textAlign,
|
||||
lineHeight = lineHeight,
|
||||
softWrap = softWrap,
|
||||
maxLines = 1,
|
||||
onTextLayout = { textLayoutResultState.value = it },
|
||||
style = style,
|
||||
modifier = modifier,
|
||||
)
|
||||
}.first().measure(Constraints())
|
||||
// to allow smart cast
|
||||
|
|
@ -151,14 +139,8 @@ fun EllipsisText(
|
|||
Text(
|
||||
text = finalText,
|
||||
color = color,
|
||||
fontSize = fontSize,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = fontWeight,
|
||||
fontFamily = fontFamily,
|
||||
letterSpacing = letterSpacing,
|
||||
textDecoration = textDecoration,
|
||||
textAlign = textAlign,
|
||||
lineHeight = lineHeight,
|
||||
softWrap = softWrap,
|
||||
onTextLayout = onTextLayout,
|
||||
style = style,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,10 @@ fun InputRowRecipient(
|
|||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
Row {
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = Modifier.heightIn(TangemTheme.dimens.size40),
|
||||
) {
|
||||
InputIcon(
|
||||
isLoading = isLoading,
|
||||
value = value,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fun PasteButton(isPasteButtonVisible: Boolean, onClick: (String) -> Unit, modifi
|
|||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.common_paste),
|
||||
style = TangemTheme.typography.button,
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.primary2,
|
||||
modifier = Modifier
|
||||
.background(
|
||||
|
|
@ -60,8 +60,8 @@ fun PasteButton(isPasteButtonVisible: Boolean, onClick: (String) -> Unit, modifi
|
|||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
)
|
||||
.padding(
|
||||
horizontal = TangemTheme.dimens.spacing10,
|
||||
vertical = TangemTheme.dimens.spacing2,
|
||||
horizontal = TangemTheme.dimens.spacing12,
|
||||
vertical = TangemTheme.dimens.spacing4,
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
|
|
@ -88,10 +88,10 @@ fun CrossIcon(onClick: (String) -> Unit, modifier: Modifier = Modifier) {
|
|||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = stringResource(R.string.common_close),
|
||||
modifier = modifier
|
||||
.size(TangemTheme.dimens.size20)
|
||||
.size(TangemTheme.dimens.size24)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(radius = TangemTheme.dimens.radius10),
|
||||
indication = rememberRipple(radius = TangemTheme.dimens.radius12),
|
||||
onClick = { onClick("") },
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ 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.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
|
|
@ -36,6 +37,7 @@ fun SelectorRowItem(
|
|||
ellipsizeOffset: Int? = null,
|
||||
isSelected: Boolean = false,
|
||||
showDivider: Boolean = true,
|
||||
showSelectedAppearance: Boolean = true,
|
||||
onSelect: (() -> Unit)? = null,
|
||||
) {
|
||||
val iconTint by animateColorAsState(
|
||||
|
|
@ -46,7 +48,11 @@ fun SelectorRowItem(
|
|||
},
|
||||
label = "Selector icon tint change",
|
||||
)
|
||||
|
||||
val textStyle = if (isSelected && showSelectedAppearance) {
|
||||
TangemTheme.typography.subtitle2
|
||||
} else {
|
||||
TangemTheme.typography.body2
|
||||
}
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -71,7 +77,7 @@ fun SelectorRowItem(
|
|||
)
|
||||
Text(
|
||||
text = stringResource(titleRes),
|
||||
style = TangemTheme.typography.body2,
|
||||
style = textStyle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
|
||||
)
|
||||
|
|
@ -80,6 +86,7 @@ fun SelectorRowItem(
|
|||
preDot = preDot,
|
||||
postDot = postDot,
|
||||
ellipsizeOffset = ellipsizeOffset,
|
||||
textStyle = textStyle,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -100,6 +107,7 @@ fun SelectorRowItem(
|
|||
private fun RowScope.SelectorValueContent(
|
||||
preDot: TextReference,
|
||||
postDot: TextReference?,
|
||||
textStyle: TextStyle,
|
||||
ellipsizeOffset: Int? = null,
|
||||
) {
|
||||
val ellipsis = if (ellipsizeOffset == null) {
|
||||
|
|
@ -109,7 +117,7 @@ private fun RowScope.SelectorValueContent(
|
|||
}
|
||||
EllipsisText(
|
||||
text = preDot.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
style = textStyle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.End,
|
||||
ellipsis = ellipsis,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ fun TransactionDoneTitle(@StringRes titleRes: Int, date: Long, modifier: Modifie
|
|||
painter = painterResource(id = R.drawable.ic_empty_in_process_64),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing8)
|
||||
.size(TangemTheme.dimens.size64),
|
||||
)
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -62,7 +62,14 @@ internal class AmountStateFactory(
|
|||
|
||||
fun getOnAmountValueChange(value: String) = amountFieldChangeConverter.convert(value)
|
||||
|
||||
fun getOnAmountReduceByState(reduceAmountBy: BigDecimal) = amountReduceByConverter.convert(reduceAmountBy)
|
||||
fun getOnAmountReduceByState(reduceAmountBy: BigDecimal, reduceAmountByDiff: BigDecimal) =
|
||||
amountReduceByConverter.convert(
|
||||
SendAmountReduceByConverter.ReduceByData(
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
reduceAmountByDiff = reduceAmountByDiff,
|
||||
),
|
||||
)
|
||||
|
||||
fun getOnAmountReduceToState(reduceAmountTo: BigDecimal) = amountReduceToConverter.convert(reduceAmountTo)
|
||||
|
||||
fun getOnMaxAmountClick(): SendUiState {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ internal class SendAmountReduceByConverter(
|
|||
private val stateRouterProvider: Provider<StateRouter>,
|
||||
private val currentStateProvider: Provider<SendUiState>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
) : Converter<BigDecimal, SendUiState> {
|
||||
override fun convert(value: BigDecimal): SendUiState {
|
||||
) : Converter<SendAmountReduceByConverter.ReduceByData, SendUiState> {
|
||||
override fun convert(value: ReduceByData): SendUiState {
|
||||
val state = currentStateProvider()
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
val isEditState = stateRouterProvider().isEditState
|
||||
|
|
@ -27,7 +27,7 @@ internal class SendAmountReduceByConverter(
|
|||
val fiatDecimals = amountTextField.fiatAmount.decimals
|
||||
val amountValue = amountState.amountTextField.cryptoAmount.value ?: return state
|
||||
|
||||
val decimalCryptoValue = amountValue.minus(value)
|
||||
val decimalCryptoValue = amountValue.minus(value.reduceAmountByDiff)
|
||||
val cryptoValue = decimalCryptoValue.parseBigDecimal(cryptoDecimals)
|
||||
val (fiatValue, decimalFiatValue) = cryptoValue.getFiatValue(
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
|
|
@ -41,7 +41,7 @@ internal class SendAmountReduceByConverter(
|
|||
return state.copyWrapped(
|
||||
isEditState = isEditState,
|
||||
sendState = state.sendState?.copy(
|
||||
reduceAmountBy = value,
|
||||
reduceAmountBy = value.reduceAmountBy,
|
||||
),
|
||||
amountState = amountState.copy(
|
||||
isPrimaryButtonEnabled = !isExceedBalance && !isZero,
|
||||
|
|
@ -59,4 +59,9 @@ internal class SendAmountReduceByConverter(
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
internal data class ReduceByData(
|
||||
val reduceAmountBy: BigDecimal,
|
||||
val reduceAmountByDiff: BigDecimal,
|
||||
)
|
||||
}
|
||||
|
|
@ -223,7 +223,8 @@ internal class SendNotificationFactory(
|
|||
),
|
||||
onConfirmClick = {
|
||||
clickIntents.onAmountReduceClick(
|
||||
reduceAmountBy = currencyDeposit.minus(diff),
|
||||
reduceAmountByDiff = currencyDeposit.minus(diff),
|
||||
reduceAmountBy = currencyDeposit,
|
||||
clazz = SendNotification.Error.ExistentialDeposit::class.java,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ internal fun checkAndCalculateSubtractedAmount(
|
|||
return if (isFeeCoverage) {
|
||||
balance.minus(reduceAmountBy).minus(feeValue)
|
||||
} else {
|
||||
amountValue.minus(reduceAmountBy)
|
||||
amountValue
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,8 +44,8 @@ internal fun checkFeeCoverage(
|
|||
reduceAmountBy: BigDecimal?,
|
||||
): Boolean {
|
||||
if (!isSubtractAvailable) return false
|
||||
val amountWithReduced = (reduceAmountBy ?: BigDecimal.ZERO) + amountValue
|
||||
return balance < amountWithReduced + feeValue && balance > feeValue && balance >= amountWithReduced
|
||||
val reducedBy = balance - (reduceAmountBy ?: BigDecimal.ZERO)
|
||||
return reducedBy < amountValue + feeValue && reducedBy > feeValue && reducedBy >= amountValue
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.tokens.model.Amount
|
|||
import com.tangem.domain.tokens.model.AmountType
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiStateType
|
||||
import com.tangem.features.send.impl.presentation.state.amount.SendAmountSegmentedButtonsConfig
|
||||
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -18,25 +19,35 @@ internal object AmountStatePreviewData {
|
|||
val amountState = SendStates.AmountState(
|
||||
type = SendUiStateType.Amount,
|
||||
isPrimaryButtonEnabled = false,
|
||||
walletName = "Wallet",
|
||||
walletBalance = stringReference("123.123"),
|
||||
walletName = "Family Wallet",
|
||||
walletBalance = stringReference("2 130,88 USDT (2 129,92 \$)"),
|
||||
tokenIconState = TokenIconState.Loading,
|
||||
segmentedButtonConfig = persistentListOf(),
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
SendAmountSegmentedButtonsConfig(
|
||||
title = stringReference("USDT"),
|
||||
iconState = TokenIconState.Locked,
|
||||
isFiat = false,
|
||||
),
|
||||
SendAmountSegmentedButtonsConfig(
|
||||
title = stringReference("USD"),
|
||||
isFiat = true,
|
||||
),
|
||||
),
|
||||
appCurrencyCode = "usd",
|
||||
amountTextField = SendTextField.AmountField(
|
||||
value = "123.123123123123123123",
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions = KeyboardActions.Default,
|
||||
cryptoAmount = Amount(
|
||||
currencySymbol = "ETH",
|
||||
value = BigDecimal(123.123),
|
||||
currencySymbol = "USDT",
|
||||
value = BigDecimal.ZERO,
|
||||
decimals = 18,
|
||||
type = AmountType.CoinType,
|
||||
),
|
||||
fiatAmount = Amount(
|
||||
currencySymbol = "$",
|
||||
value = BigDecimal(123.123),
|
||||
value = BigDecimal.ZERO,
|
||||
decimals = 2,
|
||||
type = AmountType.CoinType,
|
||||
),
|
||||
|
|
@ -52,7 +63,27 @@ internal object AmountStatePreviewData {
|
|||
selectedButton = 0,
|
||||
)
|
||||
|
||||
val fiatAmountState = amountState.copy(
|
||||
amountTextField = amountState.amountTextField.copy(isFiatValue = true),
|
||||
val amountWithValueState = amountState.copy(
|
||||
amountTextField = amountState.amountTextField.copy(
|
||||
value = "100.00",
|
||||
cryptoAmount = amountState.amountTextField.cryptoAmount.copy(
|
||||
value = BigDecimal("100.00"),
|
||||
),
|
||||
fiatValue = "99.98",
|
||||
fiatAmount = amountState.amountTextField.fiatAmount.copy(
|
||||
value = BigDecimal("99.98"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val amountWithValueFiatState = amountWithValueState.copy(
|
||||
amountTextField = amountWithValueState.amountTextField.copy(isFiatValue = false),
|
||||
)
|
||||
|
||||
val amountErrorState = amountWithValueState.copy(
|
||||
amountTextField = amountWithValueState.amountTextField.copy(
|
||||
isError = true,
|
||||
error = stringReference("Insufficient funds for transfer"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.tangem.features.send.impl.presentation.state.previewdata
|
||||
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiStateType
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object ConfirmStatePreviewData {
|
||||
|
||||
val sendState = SendStates.SendState(
|
||||
type = SendUiStateType.Send,
|
||||
isSending = false,
|
||||
isSuccess = false,
|
||||
transactionDate = 0L,
|
||||
txUrl = "",
|
||||
ignoreAmountReduce = false,
|
||||
reduceAmountBy = null,
|
||||
isFromConfirmation = false,
|
||||
showTapHelp = true,
|
||||
notifications = persistentListOf(),
|
||||
)
|
||||
|
||||
val sendDoneState = SendStates.SendState(
|
||||
type = SendUiStateType.Send,
|
||||
isSending = false,
|
||||
isSuccess = true,
|
||||
transactionDate = 1695199500000L,
|
||||
txUrl = "url",
|
||||
ignoreAmountReduce = false,
|
||||
reduceAmountBy = null,
|
||||
isFromConfirmation = false,
|
||||
showTapHelp = false,
|
||||
notifications = persistentListOf(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,56 +1,105 @@
|
|||
package com.tangem.features.send.impl.presentation.state.previewdata
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType.Coin
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiStateType
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeType
|
||||
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal object FeeStatePreviewData {
|
||||
|
||||
private val fee = Fee.Common(
|
||||
amount = Amount(
|
||||
currencySymbol = "MATIC",
|
||||
value = BigDecimal(0.159806),
|
||||
decimals = 18,
|
||||
type = Coin,
|
||||
),
|
||||
)
|
||||
|
||||
private val singleFee = TransactionFee.Single(normal = fee)
|
||||
|
||||
private val multipleFees = TransactionFee.Choosable(
|
||||
normal = fee,
|
||||
minimum = fee,
|
||||
priority = fee.copy(fee.amount.copy(value = BigDecimal(0.159824))),
|
||||
)
|
||||
|
||||
private val customValue = SendTextField.CustomFee(
|
||||
value = "0.159834",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions = KeyboardActions.Default,
|
||||
symbol = "MATIC",
|
||||
decimals = 18,
|
||||
title = stringReference("Fee up to"),
|
||||
footer = stringReference("Maximum commission amount"),
|
||||
label = stringReference("0.41 \$"),
|
||||
isReadonly = false,
|
||||
)
|
||||
|
||||
private val customValues = persistentListOf(
|
||||
customValue,
|
||||
customValue.copy(
|
||||
value = "400",
|
||||
symbol = "GWEI",
|
||||
title = stringReference("Gas price"),
|
||||
footer = stringReference("Gas Price impacts transaction speed; too low, it may not process"),
|
||||
label = null,
|
||||
),
|
||||
customValue.copy(
|
||||
value = "31400",
|
||||
symbol = "",
|
||||
title = stringReference("Gas limit"),
|
||||
footer = stringReference("Gas Limit is auto-calculated; raise it during network congestion"),
|
||||
label = null,
|
||||
),
|
||||
)
|
||||
|
||||
private val feeSelector = FeeSelectorState.Content(
|
||||
fees = singleFee,
|
||||
selectedFee = FeeType.Market,
|
||||
customValues = persistentListOf(),
|
||||
)
|
||||
|
||||
val feeState = SendStates.FeeState(
|
||||
type = SendUiStateType.Amount,
|
||||
type = SendUiStateType.Fee,
|
||||
isPrimaryButtonEnabled = false,
|
||||
feeSelectorState = FeeSelectorState.Content(
|
||||
fees = TransactionFee.Single(
|
||||
normal = Fee.Common(
|
||||
amount = Amount(
|
||||
currencySymbol = "ETH",
|
||||
value = BigDecimal(123.123),
|
||||
decimals = 18,
|
||||
type = Coin,
|
||||
),
|
||||
),
|
||||
),
|
||||
selectedFee = FeeType.Market,
|
||||
customValues = persistentListOf(),
|
||||
),
|
||||
fee = Fee.Common(
|
||||
amount = Amount(
|
||||
currencySymbol = "ETH",
|
||||
value = BigDecimal(123.123),
|
||||
decimals = 18,
|
||||
type = Coin,
|
||||
),
|
||||
),
|
||||
rate = null,
|
||||
appCurrency = AppCurrency(
|
||||
code = "USD",
|
||||
name = "USD",
|
||||
symbol = "$",
|
||||
iconSmallUrl = null,
|
||||
iconMediumUrl = null,
|
||||
),
|
||||
feeSelectorState = feeSelector,
|
||||
fee = fee,
|
||||
rate = BigDecimal.ONE,
|
||||
appCurrency = AppCurrency.Default,
|
||||
isFeeApproximate = false,
|
||||
notifications = persistentListOf(),
|
||||
isCustomSelected = false,
|
||||
)
|
||||
|
||||
val feeChoosableState = feeState.copy(
|
||||
feeSelectorState = feeSelector.copy(
|
||||
fees = multipleFees,
|
||||
customValues = customValues,
|
||||
),
|
||||
)
|
||||
|
||||
val feeCustomState = feeState.copy(
|
||||
feeSelectorState = feeSelector.copy(
|
||||
fees = multipleFees,
|
||||
customValues = customValues,
|
||||
selectedFee = FeeType.Custom,
|
||||
),
|
||||
isCustomSelected = true,
|
||||
)
|
||||
|
||||
val errorFeeState = feeState.copy(
|
||||
feeSelectorState = FeeSelectorState.Error,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ internal object RecipientStatePreviewData {
|
|||
|
||||
private val defaultRecentItem = SendRecipientListContent(
|
||||
id = "sanctus",
|
||||
title = stringReference("address"),
|
||||
subtitle = stringReference("0.001 BTC"),
|
||||
timestamp = stringReference("1.01.1970, 00:00"),
|
||||
title = stringReference("0x391316a070212312312378E88CAc8A0C250"),
|
||||
subtitleEndOffset = 0,
|
||||
subtitleIconRes = R.drawable.ic_arrow_down_24,
|
||||
isVisible = true,
|
||||
|
|
@ -23,26 +21,65 @@ internal object RecipientStatePreviewData {
|
|||
|
||||
val recipientState = SendStates.RecipientState(
|
||||
addressTextField = SendTextField.RecipientAddress(
|
||||
value = "0x23948239805671983476598176",
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions.Default,
|
||||
placeholder = stringReference("Placeholder"),
|
||||
placeholder = stringReference("Enter address"),
|
||||
label = stringReference("Recipient"),
|
||||
isError = false,
|
||||
error = null,
|
||||
isValuePasted = false,
|
||||
),
|
||||
memoTextField = null,
|
||||
recent = persistentListOf(
|
||||
defaultRecentItem.copy(id = "1"),
|
||||
defaultRecentItem.copy(id = "2"),
|
||||
defaultRecentItem.copy(id = "3"),
|
||||
),
|
||||
wallets = persistentListOf(
|
||||
defaultRecentItem.copy(id = "4", subtitle = stringReference("Wallet")),
|
||||
memoTextField = SendTextField.RecipientMemo(
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions.Default,
|
||||
placeholder = stringReference("Optional"),
|
||||
label = stringReference("Memo"),
|
||||
isError = false,
|
||||
error = null,
|
||||
disabledText = stringReference("Already included in the entered address"),
|
||||
isEnabled = true,
|
||||
isValuePasted = false,
|
||||
),
|
||||
recent = persistentListOf(),
|
||||
wallets = persistentListOf(),
|
||||
network = "Ethereum",
|
||||
isValidating = false,
|
||||
isPrimaryButtonEnabled = true,
|
||||
)
|
||||
|
||||
val recipientAddressState = recipientState.copy(
|
||||
addressTextField = recipientState.addressTextField.copy(
|
||||
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
|
||||
),
|
||||
)
|
||||
|
||||
val recipientWithRecentState = recipientState.copy(
|
||||
recent = persistentListOf(
|
||||
defaultRecentItem.copy(
|
||||
id = "1",
|
||||
subtitle = stringReference("1 000 000 000.0004 USDT"),
|
||||
timestamp = stringReference("today at 14:46"),
|
||||
subtitleIconRes = R.drawable.ic_arrow_up_24,
|
||||
),
|
||||
defaultRecentItem.copy(
|
||||
id = "2",
|
||||
subtitle = stringReference("20,09 USDT"),
|
||||
timestamp = stringReference("24.05.2004 at 14:46"),
|
||||
),
|
||||
defaultRecentItem.copy(
|
||||
id = "3",
|
||||
subtitle = stringReference("20,09 USDT"),
|
||||
timestamp = stringReference("24.05.2004 at 14:46"),
|
||||
),
|
||||
),
|
||||
wallets = persistentListOf(
|
||||
defaultRecentItem.copy(
|
||||
id = "4",
|
||||
subtitle = stringReference("Main Wallet"),
|
||||
subtitleIconRes = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -62,6 +62,7 @@ internal object SendClickIntentsStub : SendClickIntents {
|
|||
|
||||
override fun onAmountReduceClick(
|
||||
reduceAmountBy: BigDecimal?,
|
||||
reduceAmountByDiff: BigDecimal?,
|
||||
reduceAmountTo: BigDecimal?,
|
||||
clazz: Class<out SendNotification>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.features.send.impl.presentation.state.previewdata
|
||||
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiState
|
||||
|
||||
internal object SendStatesPreviewData {
|
||||
|
||||
val uiState = SendUiState(
|
||||
clickIntents = SendClickIntentsStub,
|
||||
isEditingDisabled = false,
|
||||
cryptoCurrencyName = "",
|
||||
amountState = AmountStatePreviewData.amountWithValueState,
|
||||
recipientState = RecipientStatePreviewData.recipientAddressState,
|
||||
feeState = FeeStatePreviewData.feeChoosableState,
|
||||
sendState = ConfirmStatePreviewData.sendState,
|
||||
editAmountState = AmountStatePreviewData.amountWithValueState,
|
||||
editRecipientState = RecipientStatePreviewData.recipientAddressState,
|
||||
editFeeState = FeeStatePreviewData.feeChoosableState,
|
||||
isBalanceHidden = false,
|
||||
isSubtracted = false,
|
||||
event = consumedEvent(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.features.send.impl.presentation.ui.amount
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
|
@ -7,12 +9,11 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
|
||||
import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons
|
||||
import com.tangem.core.ui.components.currency.fiaticon.FiatIcon
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIcon
|
||||
|
|
@ -60,17 +61,23 @@ internal fun LazyListScope.buttons(
|
|||
} else {
|
||||
SpacerWMax()
|
||||
}
|
||||
SecondaryButton(
|
||||
Text(
|
||||
text = stringResource(R.string.send_max_amount),
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
clickIntents.onMaxValueClick()
|
||||
},
|
||||
size = TangemButtonSize.Text,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius26),
|
||||
style = TangemTheme.typography.button,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.height(TangemTheme.dimens.size40),
|
||||
.height(TangemTheme.dimens.size40)
|
||||
.clip(shape = RoundedCornerShape(TangemTheme.dimens.radius26))
|
||||
.background(TangemTheme.colors.button.secondary)
|
||||
.clickable {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
clickIntents.onMaxValueClick()
|
||||
}
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens.spacing10,
|
||||
horizontal = TangemTheme.dimens.spacing34,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ internal fun SendAmountContent(
|
|||
// Do not put fillMaxSize() in here
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
)
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
),
|
||||
) {
|
||||
amountField(amountState = amountState, isBalanceHiding = isBalanceHiding)
|
||||
buttons(
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ private fun ListItemWithIcon(
|
|||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
modifier = Modifier
|
||||
.padding(end = TangemTheme.dimens.spacing2)
|
||||
.size(TangemTheme.dimens.size16)
|
||||
.background(TangemTheme.colors.background.tertiary, CircleShape)
|
||||
.padding(TangemTheme.dimens.spacing2),
|
||||
|
|
@ -139,7 +140,6 @@ private fun ListItemWithIcon(
|
|||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(offsetEnd = offset),
|
||||
modifier = Modifier.padding(start = TangemTheme.dimens.spacing2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.send.impl.presentation.ui.recipient
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -139,6 +140,7 @@ private fun LazyListScope.memoField(memoField: SendTextField.RecipientMemo?, onM
|
|||
onValueChange = memoField.onValueChange,
|
||||
onPasteClick = onMemoChange,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing20),
|
||||
labelStyle = TangemTheme.typography.caption2,
|
||||
isError = memoField.isError,
|
||||
error = memoField.error,
|
||||
isReadOnly = !memoField.isEnabled,
|
||||
|
|
@ -251,7 +253,9 @@ private fun AnimateRecentAppearance(isVisible: Boolean, content: @Composable ()
|
|||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, heightDp = 800)
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun SendRecipientContent_Preview(
|
||||
@PreviewParameter(SendRecipientContentPreviewProvider::class) recipientState: SendStates.RecipientState,
|
||||
|
|
@ -268,6 +272,9 @@ private fun SendRecipientContent_Preview(
|
|||
private class SendRecipientContentPreviewProvider : PreviewParameterProvider<SendStates.RecipientState> {
|
||||
override val values: Sequence<SendStates.RecipientState>
|
||||
get() = sequenceOf(
|
||||
RecipientStatePreviewData.recipientWithRecentState,
|
||||
RecipientStatePreviewData.recipientState,
|
||||
RecipientStatePreviewData.recipientAddressState,
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment.Companion.CenterEnd
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import com.tangem.core.ui.components.fields.SimpleTextField
|
||||
import com.tangem.core.ui.components.inputrow.inner.CrossIcon
|
||||
import com.tangem.core.ui.components.inputrow.inner.PasteButton
|
||||
|
|
@ -27,6 +28,7 @@ internal fun TextFieldWithPaste(
|
|||
onPasteClick: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
footer: String? = null,
|
||||
labelStyle: TextStyle = TangemTheme.typography.body2,
|
||||
error: TextReference? = null,
|
||||
isError: Boolean = false,
|
||||
isReadOnly: Boolean = false,
|
||||
|
|
@ -45,7 +47,7 @@ internal fun TextFieldWithPaste(
|
|||
color = TangemTheme.colors.background.action,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
)
|
||||
.padding(end = TangemTheme.dimens.spacing16),
|
||||
.padding(end = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Row {
|
||||
Column(
|
||||
|
|
@ -55,7 +57,7 @@ internal fun TextFieldWithPaste(
|
|||
) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
style = labelStyle,
|
||||
color = color,
|
||||
)
|
||||
SimpleTextField(
|
||||
|
|
@ -67,7 +69,7 @@ internal fun TextFieldWithPaste(
|
|||
isValuePasted = isValuePasted,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = TangemTheme.dimens.spacing6),
|
||||
.padding(top = TangemTheme.dimens.spacing8),
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ internal fun AmountBlock(
|
|||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = TangemTheme.dimens.spacing16),
|
||||
.padding(top = TangemTheme.dimens.spacing24),
|
||||
)
|
||||
Text(
|
||||
text = secondAmount,
|
||||
|
|
@ -79,7 +79,10 @@ internal fun AmountBlock(
|
|||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = TangemTheme.dimens.spacing4),
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing8,
|
||||
bottom = TangemTheme.dimens.spacing2,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, o
|
|||
ellipsizeOffset = feeAmount?.currencySymbol?.length,
|
||||
isSelected = true,
|
||||
showDivider = false,
|
||||
showSelectedAppearance = false,
|
||||
paddingValues = PaddingValues(),
|
||||
)
|
||||
FeeLoading(feeSelectorState)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ private fun LazyListScope.blocks(uiState: SendUiState) {
|
|||
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12)) {
|
||||
AnimatedVisibility(
|
||||
visible = isSuccess,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
TransactionDoneTitle(
|
||||
titleRes = R.string.sent_transaction_sent_title,
|
||||
|
|
@ -120,7 +120,7 @@ private fun LazyListScope.tapHelp(isDisplay: Boolean, modifier: Modifier = Modif
|
|||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.send_summary_tap_hint),
|
||||
style = TangemTheme.typography.caption1,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ internal interface SendClickIntents {
|
|||
|
||||
fun onAmountReduceClick(
|
||||
reduceAmountBy: BigDecimal? = null,
|
||||
reduceAmountByDiff: BigDecimal? = reduceAmountBy,
|
||||
reduceAmountTo: BigDecimal? = null,
|
||||
clazz: Class<out SendNotification>,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -807,11 +807,15 @@ internal class SendViewModel @Inject constructor(
|
|||
|
||||
override fun onAmountReduceClick(
|
||||
reduceAmountBy: BigDecimal?,
|
||||
reduceAmountByDiff: BigDecimal?,
|
||||
reduceAmountTo: BigDecimal?,
|
||||
clazz: Class<out SendNotification>,
|
||||
) {
|
||||
uiState = when {
|
||||
reduceAmountBy != null -> amountStateFactory.getOnAmountReduceByState(reduceAmountBy)
|
||||
reduceAmountBy != null && reduceAmountByDiff != null -> amountStateFactory.getOnAmountReduceByState(
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
reduceAmountByDiff = reduceAmountByDiff,
|
||||
)
|
||||
reduceAmountTo != null -> amountStateFactory.getOnAmountReduceToState(reduceAmountTo)
|
||||
else -> return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ internal class StateBuilder(
|
|||
warnings.add(
|
||||
SwapWarning.ReduceAmount(
|
||||
notificationConfig = createReduceAmountNotificationConfig(
|
||||
currencyName = quoteModel.fromTokenInfo.cryptoCurrencyStatus.currency.name,
|
||||
amount = it.tezosFeeThreshold.toPlainString(),
|
||||
onConfirmClick = {
|
||||
val fromAmount = quoteModel.fromTokenInfo.tokenAmount
|
||||
|
|
@ -1385,10 +1386,14 @@ internal class StateBuilder(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createReduceAmountNotificationConfig(amount: String, onConfirmClick: () -> Unit): NotificationConfig {
|
||||
private fun createReduceAmountNotificationConfig(
|
||||
currencyName: String,
|
||||
amount: String,
|
||||
onConfirmClick: () -> Unit,
|
||||
): NotificationConfig {
|
||||
return NotificationConfig(
|
||||
title = resourceReference(R.string.send_notification_high_fee_title),
|
||||
subtitle = resourceReference(R.string.send_notification_high_fee_text, wrappedList(amount)),
|
||||
subtitle = resourceReference(R.string.send_notification_high_fee_text, wrappedList(currencyName, amount)),
|
||||
iconResId = R.drawable.img_attention_20,
|
||||
buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(R.string.xtz_withdrawal_message_reduce, wrappedList(amount)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue