Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-28 15:42:48 +05:00
commit f71fe3aa6b
27 changed files with 331 additions and 120 deletions

View file

@ -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,
)
}

View file

@ -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,

View file

@ -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,

View file

@ -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("") },
),
)

View file

@ -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,

View file

@ -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(

View file

@ -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 {

View file

@ -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,
)
}

View file

@ -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,
)
},

View file

@ -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
}
/**

View file

@ -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"),
),
)
}

View file

@ -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(),
)
}

View file

@ -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,
)

View file

@ -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,
),
),
)
}

View file

@ -62,6 +62,7 @@ internal object SendClickIntentsStub : SendClickIntents {
override fun onAmountReduceClick(
reduceAmountBy: BigDecimal?,
reduceAmountByDiff: BigDecimal?,
reduceAmountTo: BigDecimal?,
clazz: Class<out SendNotification>,
) {

View file

@ -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(),
)
}

View file

@ -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,
),
)
}
}

View file

@ -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(

View file

@ -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),
)
}
}

View file

@ -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

View file

@ -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(

View file

@ -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,
),
)
}
}

View file

@ -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)

View file

@ -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)

View file

@ -69,6 +69,7 @@ internal interface SendClickIntents {
fun onAmountReduceClick(
reduceAmountBy: BigDecimal? = null,
reduceAmountByDiff: BigDecimal? = reduceAmountBy,
reduceAmountTo: BigDecimal? = null,
clazz: Class<out SendNotification>,
)

View file

@ -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
}

View file

@ -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)),