diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index b6ec8f4866..f71126d7f2 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -425,7 +425,7 @@ Приготовьте свою карту Уже содержится в введенном адресе Вычесть - Недостаточно средств для покрытия комиссии сети. Вычесть комиссию из отправляемой сумму? + Недостаточно средств для покрытия комиссии сети. Вычесть комиссию %s из отправляемой сумму? Вы указали комиссию ниже рекомендуемой, это может привести к задержке исполнения вашей транзакции. Продолжить? Причина: %1$s\nКод: %2$s Транзакция не выполнена diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index ce3ef5fed6..8e0afa7d1e 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -421,7 +421,7 @@ Get your card ready! Already included in the entered address Subtract - Not enough funds to cover the network commission. Subtract the commission from the amount sent? + Not enough funds to cover the network commission. Subtract the commission %s from the amount sent? You specified a commission below the recommended amount, which could cause a delay in your transaction. Continue? Reason: %1$s\nCode: %2$s The transaction is not completed diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt index 229fbe444c..2bd0141ea1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt @@ -45,6 +45,7 @@ fun AppBarWithBackButtonAndIconContent( ) { Row( modifier = modifier + .height(TangemTheme.dimens.size56) .background(color = backgroundColor) .fillMaxWidth() .padding(horizontal = TangemTheme.dimens.spacing16), diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt index 30becd1f7e..93bb812fae 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt @@ -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) } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt index 490e25e8e1..2928e3d1f6 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt @@ -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, ), ), diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt index 752a235ce0..631191ad66 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt @@ -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), diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt index bb10ce4ab4..d16f511bbd 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt @@ -105,6 +105,6 @@ enum class SendUiStateType { None, Recipient, Amount, - Fee, Send, + Fee, } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt index 85402bfc8f..8b5e5530c2 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt @@ -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, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/SendAmountContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/SendAmountContent.kt index 3f3d18d3bd..d1cb3b1dca 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/SendAmountContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/SendAmountContent.kt @@ -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( @@ -31,29 +26,4 @@ internal fun SendAmountContent( buttons(amountState.segmentedButtonConfig, clickIntents) notifications(amountState.notifications) } -} - -@OptIn(ExperimentalFoundationApi::class) -internal fun LazyListScope.notifications(configs: ImmutableList, 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 - }, - ) - }, - ) } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/common/Notifications.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/common/Notifications.kt new file mode 100644 index 0000000000..21791d730d --- /dev/null +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/common/Notifications.kt @@ -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, + 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 + }, + ) + }, + ) +} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendCustomFeeEthereum.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendCustomFeeEthereum.kt index 92d9b44d51..2276dc4848 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendCustomFeeEthereum.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendCustomFeeEthereum.kt @@ -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( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt index c17e9c4458..cb132488c6 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt @@ -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, 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), + ) } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt index 134cea2336..3a31549af5 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt @@ -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, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt index c5be1f7b27..78809756c4 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt @@ -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, 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 - }, - ) - }, - ) } \ No newline at end of file