Updated on 2026-08-14
This commit is contained in:
commit
78147170d2
14 changed files with 114 additions and 123 deletions
|
|
@ -425,7 +425,7 @@
|
|||
<string name="scan_card_settings_title">Приготовьте свою карту</string>
|
||||
<string name="send_additional_field_already_included">Уже содержится в введенном адресе</string>
|
||||
<string name="send_alert_fee_coverage_subract_text">Вычесть</string>
|
||||
<string name="send_alert_fee_coverage_title">Недостаточно средств для покрытия комиссии сети. Вычесть комиссию из отправляемой сумму?</string>
|
||||
<string name="send_alert_fee_coverage_title">Недостаточно средств для покрытия комиссии сети. Вычесть комиссию %s из отправляемой сумму?</string>
|
||||
<string name="send_alert_fee_too_low_text">Вы указали комиссию ниже рекомендуемой, это может привести к задержке исполнения вашей транзакции. Продолжить?</string>
|
||||
<string name="send_alert_transaction_failed_text">Причина: %1$s\nКод: %2$s</string>
|
||||
<string name="send_alert_transaction_failed_title">Транзакция не выполнена</string>
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@
|
|||
<string name="scan_card_settings_title">Get your card ready!</string>
|
||||
<string name="send_additional_field_already_included">Already included in the entered address</string>
|
||||
<string name="send_alert_fee_coverage_subract_text">Subtract</string>
|
||||
<string name="send_alert_fee_coverage_title">Not enough funds to cover the network commission. Subtract the commission from the amount sent?</string>
|
||||
<string name="send_alert_fee_coverage_title">Not enough funds to cover the network commission. Subtract the commission %s from the amount sent?</string>
|
||||
<string name="send_alert_fee_too_low_text">You specified a commission below the recommended amount, which could cause a delay in your transaction. Continue?</string>
|
||||
<string name="send_alert_transaction_failed_text">Reason: %1$s\nCode: %2$s</string>
|
||||
<string name="send_alert_transaction_failed_title">The transaction is not completed</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ fun AppBarWithBackButtonAndIconContent(
|
|||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.height(TangemTheme.dimens.size56)
|
||||
.background(color = backgroundColor)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
|
|
|
|||
|
|
@ -59,10 +59,12 @@ internal sealed class SendAlertState {
|
|||
}
|
||||
|
||||
data class FeeCoverage(
|
||||
val amount: String,
|
||||
override val onConfirmClick: (() -> Unit),
|
||||
) : SendAlertState() {
|
||||
override val title: TextReference? = null
|
||||
override val message: TextReference = resourceReference(id = R.string.send_alert_fee_coverage_title)
|
||||
override val message: TextReference =
|
||||
resourceReference(id = R.string.send_alert_fee_coverage_title, wrappedList(amount))
|
||||
override val confirmButtonText: TextReference =
|
||||
resourceReference(id = R.string.send_alert_fee_coverage_subract_text)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.send.impl.presentation.state
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeStateFactory
|
||||
|
|
@ -45,10 +46,17 @@ internal class SendEventStateFactory(
|
|||
|
||||
fun getFeeCoverageAlert(onConsume: () -> Unit): SendUiState {
|
||||
val state = currentStateProvider()
|
||||
val amount = state.feeState?.fee?.amount ?: return state
|
||||
val feeAmount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = amount.value,
|
||||
cryptoCurrency = state.cryptoCurrencySymbol,
|
||||
decimals = amount.decimals,
|
||||
)
|
||||
return state.copy(
|
||||
event = triggeredEvent(
|
||||
data = SendEvent.ShowAlert(
|
||||
SendAlertState.FeeCoverage(
|
||||
amount = feeAmount,
|
||||
onConfirmClick = clickIntents::onSubtractSelect,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -95,6 +95,11 @@ internal sealed class SendNotification(val config: NotificationConfig) {
|
|||
)
|
||||
},
|
||||
)
|
||||
|
||||
data class ExistentialDeposit(val deposit: String) : Error(
|
||||
title = resourceReference(R.string.send_notification_existential_deposit_title),
|
||||
subtitle = resourceReference(R.string.send_notification_existential_deposit_text, wrappedList(deposit)),
|
||||
)
|
||||
}
|
||||
|
||||
sealed class Warning(
|
||||
|
|
@ -125,11 +130,6 @@ internal sealed class SendNotification(val config: NotificationConfig) {
|
|||
onCloseClick = onCloseClick,
|
||||
)
|
||||
|
||||
data class ExistentialDeposit(val deposit: String) : Warning(
|
||||
title = resourceReference(R.string.send_notification_existential_deposit_title),
|
||||
subtitle = resourceReference(R.string.send_notification_existential_deposit_text, wrappedList(deposit)),
|
||||
)
|
||||
|
||||
data object FeeTooLow : Warning(
|
||||
title = resourceReference(id = R.string.send_notification_transaction_delay_title),
|
||||
subtitle = resourceReference(id = R.string.send_notification_transaction_delay_text),
|
||||
|
|
|
|||
|
|
@ -105,6 +105,6 @@ enum class SendUiStateType {
|
|||
None,
|
||||
Recipient,
|
||||
Amount,
|
||||
Fee,
|
||||
Send,
|
||||
Fee,
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@ internal class SendNotificationFactory(
|
|||
)
|
||||
if (currencyDeposit != null && currencyDeposit > spendingAmount) {
|
||||
add(
|
||||
SendNotification.Warning.ExistentialDeposit(
|
||||
SendNotification.Error.ExistentialDeposit(
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = currencyDeposit,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,14 @@
|
|||
package com.tangem.features.send.impl.presentation.ui.amount
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.ui.common.notifications
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
internal fun SendAmountContent(
|
||||
|
|
@ -35,29 +30,4 @@ internal fun SendAmountContent(
|
|||
)
|
||||
notifications(amountState.notifications)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
internal fun LazyListScope.notifications(configs: ImmutableList<SendNotification>, modifier: Modifier = Modifier) {
|
||||
items(
|
||||
items = configs,
|
||||
key = { it::class.java },
|
||||
contentType = { it::class.java },
|
||||
itemContent = {
|
||||
val bottomPadding = if (it == configs.last()) TangemTheme.dimens.spacing12 else TangemTheme.dimens.spacing0
|
||||
Notification(
|
||||
config = it.config,
|
||||
modifier = modifier
|
||||
.animateItemPlacement()
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
bottom = bottomPadding,
|
||||
),
|
||||
containerColor = when (it) {
|
||||
is SendNotification.Warning.NetworkFeeUnreachable -> TangemTheme.colors.background.action
|
||||
else -> TangemTheme.colors.button.disabled
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.tangem.features.send.impl.presentation.ui.common
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
internal fun LazyListScope.notifications(
|
||||
notifications: ImmutableList<SendNotification>,
|
||||
modifier: Modifier = Modifier,
|
||||
hasPaddingAbove: Boolean = false,
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = notifications,
|
||||
key = { _, item -> item::class.java },
|
||||
contentType = { _, item -> item::class.java },
|
||||
itemContent = { i, item ->
|
||||
val bottomPadding = if (i == notifications.lastIndex) {
|
||||
TangemTheme.dimens.spacing12
|
||||
} else {
|
||||
TangemTheme.dimens.spacing0
|
||||
}
|
||||
val topPadding = if (i == 0 && hasPaddingAbove) {
|
||||
TangemTheme.dimens.spacing0
|
||||
} else {
|
||||
TangemTheme.dimens.spacing12
|
||||
}
|
||||
Notification(
|
||||
config = item.config,
|
||||
modifier = modifier
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = bottomPadding,
|
||||
)
|
||||
.animateItemPlacement(),
|
||||
containerColor = when (item) {
|
||||
is SendNotification.Error.ExceedsBalance,
|
||||
is SendNotification.Warning.NetworkFeeUnreachable,
|
||||
is SendNotification.Warning.HighFeeError,
|
||||
-> TangemTheme.colors.background.action
|
||||
else -> TangemTheme.colors.button.disabled
|
||||
},
|
||||
iconTint = when (item) {
|
||||
is SendNotification.Error.ExceedsBalance,
|
||||
is SendNotification.Warning,
|
||||
-> null
|
||||
is SendNotification.Error -> TangemTheme.colors.icon.warning
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.features.send.impl.presentation.ui.fee
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.inputrow.InputRowEnterAmount
|
||||
|
|
@ -24,6 +25,8 @@ internal fun SendCustomFeeEthereum(
|
|||
AnimatedVisibility(
|
||||
visible = selectedFee == FeeType.Custom && customValues.isNotEmpty(),
|
||||
label = "Custom Fee Selected Animation",
|
||||
enter = expandVertically().plus(fadeIn()),
|
||||
exit = shrinkVertically().plus(fadeOut()),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
|
|
@ -31,8 +34,14 @@ internal fun SendCustomFeeEthereum(
|
|||
) {
|
||||
repeat(customValues.size) { index ->
|
||||
val value = customValues[index]
|
||||
val bottomPadding = if (index == customValues.lastIndex) {
|
||||
TangemTheme.dimens.spacing12
|
||||
} else {
|
||||
TangemTheme.dimens.spacing0
|
||||
}
|
||||
FooterContainer(
|
||||
footer = value.footer.resolveReference(),
|
||||
modifier = Modifier.padding(bottom = bottomPadding),
|
||||
) {
|
||||
if (value.label != null) {
|
||||
InputRowEnterInfoAmount(
|
||||
|
|
|
|||
|
|
@ -7,16 +7,14 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
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.ui.common.notifications
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
private const val FEE_SELECTOR_KEY = "FEE_SELECTOR_KEY"
|
||||
private const val FEE_CUSTOM_KEY = "FEE_CUSTOM_KEY"
|
||||
|
|
@ -24,7 +22,8 @@ private const val FEE_CUSTOM_KEY = "FEE_CUSTOM_KEY"
|
|||
@Composable
|
||||
internal fun SendSpeedAndFeeContent(state: SendStates.FeeState?, clickIntents: SendClickIntents) {
|
||||
if (state == null) return
|
||||
val feeSendState = state.feeSelectorState
|
||||
val feeSendState = state.feeSelectorState as? FeeSelectorState.Content
|
||||
val isCustomSelected = feeSendState?.selectedFee == FeeType.Custom
|
||||
val notifications = state.notifications
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
|
|
@ -35,8 +34,10 @@ internal fun SendSpeedAndFeeContent(state: SendStates.FeeState?, clickIntents: S
|
|||
),
|
||||
) {
|
||||
feeSelector(state, clickIntents)
|
||||
customFee(feeSendState)
|
||||
notifications(notifications)
|
||||
if (feeSendState != null) {
|
||||
customFee(feeSendState)
|
||||
}
|
||||
notifications(notifications = notifications, hasPaddingAbove = isCustomSelected)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,45 +55,18 @@ private fun LazyListScope.feeSelector(state: SendStates.FeeState, clickIntents:
|
|||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
private fun LazyListScope.notifications(configs: ImmutableList<SendNotification>, modifier: Modifier = Modifier) {
|
||||
items(
|
||||
items = configs,
|
||||
key = { it::class.java },
|
||||
contentType = { it::class.java },
|
||||
itemContent = {
|
||||
val bottomPadding = if (it == configs.last()) TangemTheme.dimens.spacing12 else TangemTheme.dimens.spacing0
|
||||
Notification(
|
||||
config = it.config,
|
||||
modifier = modifier
|
||||
.padding(
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
bottom = bottomPadding,
|
||||
)
|
||||
.animateItemPlacement(),
|
||||
containerColor = when (it) {
|
||||
is SendNotification.Warning.NetworkFeeUnreachable -> TangemTheme.colors.background.action
|
||||
else -> TangemTheme.colors.button.disabled
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
internal fun LazyListScope.customFee(feeSendState: FeeSelectorState, modifier: Modifier = Modifier) {
|
||||
if (feeSendState is FeeSelectorState.Content) {
|
||||
item(
|
||||
key = FEE_CUSTOM_KEY,
|
||||
) {
|
||||
SendCustomFeeEthereum(
|
||||
customValues = feeSendState.customValues,
|
||||
selectedFee = feeSendState.selectedFee,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.animateItemPlacement()
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(top = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
internal fun LazyListScope.customFee(feeSendState: FeeSelectorState.Content, modifier: Modifier = Modifier) {
|
||||
item(
|
||||
key = FEE_CUSTOM_KEY,
|
||||
) {
|
||||
SendCustomFeeEthereum(
|
||||
customValues = feeSendState.customValues,
|
||||
selectedFee = feeSendState.selectedFee,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.animateItemPlacement()
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(top = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,6 @@ internal fun SendRecipientContent(uiState: SendStates.RecipientState?, clickInte
|
|||
isLoading = isValidating,
|
||||
error = address.error,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing4)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.action,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -18,13 +17,11 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.impl.R
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import com.tangem.features.send.impl.presentation.ui.common.notifications
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
private const val TAP_HELP_KEY = "TAP_HELP_KEY"
|
||||
|
|
@ -39,7 +36,6 @@ internal fun SendContent(uiState: SendUiState) {
|
|||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
blocks(uiState)
|
||||
tapHelp(isDisplay = sendState.showTapHelp)
|
||||
|
|
@ -109,7 +105,8 @@ private fun LazyListScope.tapHelp(isDisplay: Boolean, modifier: Modifier = Modif
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.animateItemPlacement(),
|
||||
.animateItemPlacement()
|
||||
.padding(top = TangemTheme.dimens.spacing20),
|
||||
) {
|
||||
val background = TangemTheme.colors.button.secondary
|
||||
Icon(
|
||||
|
|
@ -133,31 +130,4 @@ private fun LazyListScope.tapHelp(isDisplay: Boolean, modifier: Modifier = Modif
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
internal fun LazyListScope.notifications(configs: ImmutableList<SendNotification>, modifier: Modifier = Modifier) {
|
||||
items(
|
||||
items = configs,
|
||||
key = { it::class.java },
|
||||
contentType = { it::class.java },
|
||||
itemContent = {
|
||||
Notification(
|
||||
config = it.config,
|
||||
modifier = modifier.animateItemPlacement(),
|
||||
containerColor = when (it) {
|
||||
is SendNotification.Error.ExceedsBalance,
|
||||
is SendNotification.Warning.HighFeeError,
|
||||
-> TangemTheme.colors.background.action
|
||||
else -> TangemTheme.colors.button.disabled
|
||||
},
|
||||
iconTint = when (it) {
|
||||
is SendNotification.Error.ExceedsBalance,
|
||||
is SendNotification.Warning,
|
||||
-> null
|
||||
is SendNotification.Error -> TangemTheme.colors.icon.warning
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue