diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt index 9c30cb4f8e..2809ea5cb4 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt @@ -13,6 +13,8 @@ internal sealed class YieldSupplyFeeUM { data class Content( val transactionDataList: ImmutableList, val feeValue: TextReference, + val currentNetworkFeeValue: TextReference, + val maxNetworkFeeValue: TextReference, ) : YieldSupplyFeeUM() } @@ -20,6 +22,7 @@ internal data class YieldSupplyActionUM( val title: TextReference, val subtitle: TextReference, val footer: TextReference, + val footerLink: TextReference, val currencyIconState: CurrencyIconState, val yieldSupplyFeeUM: YieldSupplyFeeUM, val isPrimaryButtonEnabled: Boolean, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt index 98746a3d45..ac82f7b925 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt @@ -3,18 +3,19 @@ package com.tangem.features.yield.supply.impl.common.ui import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape 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.text.LinkAnnotation import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withLink 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.dp -import com.tangem.core.ui.components.* +import com.tangem.core.ui.components.SpacerH24 +import com.tangem.core.ui.components.SpacerH8 import com.tangem.core.ui.components.containers.FooterContainer import com.tangem.core.ui.components.currency.icon.CurrencyIcon import com.tangem.core.ui.components.currency.icon.CurrencyIconState @@ -30,6 +31,7 @@ import kotlinx.collections.immutable.persistentListOf @Composable internal fun YieldSupplyActionContent( yieldSupplyActionUM: YieldSupplyActionUM, + onFooterClick: () -> Unit, modifier: Modifier = Modifier, iconContent: @Composable ColumnScope.() -> Unit, ) { @@ -54,47 +56,31 @@ internal fun YieldSupplyActionContent( ) SpacerH24() FooterContainer( - footer = yieldSupplyActionUM.footer, + footer = annotatedReference { + append(yieldSupplyActionUM.footer.resolveReference()) + appendSpace() + withLink(link = LinkAnnotation.Clickable("LINK_TAG") { onFooterClick() }) { + appendColored( + text = yieldSupplyActionUM.footerLink.resolveReference(), + color = TangemTheme.colors.icon.accent, + ) + } + }, paddingValues = PaddingValues( start = 12.dp, end = 12.dp, top = 8.dp, ), ) { - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(TangemTheme.colors.background.action) - .padding(horizontal = 16.dp, vertical = 12.dp), - ) { - Text( - text = stringResourceSafe(R.string.common_network_fee_title), - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.primary1, - ) - SpacerWMax() - when (val fee = yieldSupplyActionUM.yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> Text( - text = fee.feeValue.resolveReference(), - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.tertiary, - ) - YieldSupplyFeeUM.Error -> Text( - text = stringResourceSafe(R.string.common_fee_error), - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.attention, - ) - YieldSupplyFeeUM.Loading -> { - TextShimmer( - style = TangemTheme.typography.body1, - text = stringResourceSafe(R.string.common_fee_error), - ) - } - } + val fee = when (val yieldSupplyFeeUM = yieldSupplyActionUM.yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null } + YieldSupplyFeeRow( + title = resourceReference(R.string.common_network_fee_title), + value = fee, + ) } } } @@ -109,6 +95,7 @@ private fun YieldSupplyActionContent_Preview( TangemThemePreview { YieldSupplyActionContent( yieldSupplyActionUM = params, + onFooterClick = {}, modifier = Modifier.background(TangemTheme.colors.background.tertiary), ) { CurrencyIcon( @@ -130,15 +117,14 @@ private class YieldSupplyActionContentPreviewProvider : PreviewParameterProvider R.string.yield_module_start_earning_sheet_description, wrappedList("USDT"), ), - footer = combinedReference( - resourceReference(R.string.yield_module_start_earning_sheet_next_deposits), - stringReference(StringsSigns.WHITE_SPACE), - resourceReference(R.string.yield_module_start_earning_sheet_fee_policy), - ), + footer = resourceReference(R.string.yield_module_start_earning_sheet_next_deposits), + footerLink = resourceReference(R.string.yield_module_start_earning_sheet_fee_policy), currencyIconState = CurrencyIconState.Loading, yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = persistentListOf(), feeValue = stringReference("0.00020 ETH • \$0.99"), + currentNetworkFeeValue = stringReference("1.45 USDT • \$1.45"), + maxNetworkFeeValue = stringReference("8.50 USDT • \$8.50"), ), isPrimaryButtonEnabled = false, ), diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt new file mode 100644 index 0000000000..2f2901b79d --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt @@ -0,0 +1,58 @@ +package com.tangem.features.yield.supply.impl.common.ui + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +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.unit.dp +import com.tangem.core.ui.components.SpacerWMax +import com.tangem.core.ui.components.TextShimmer +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.yield.supply.impl.R + +@Composable +internal fun YieldSupplyFeeRow(title: TextReference, value: TextReference?) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(TangemTheme.colors.background.action) + .padding(horizontal = 16.dp, vertical = 12.dp), + ) { + Text( + text = title.resolveReference(), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.primary1, + ) + SpacerWMax() + AnimatedContent( + targetState = value, + ) { targetValue -> + if (targetValue != null) { + Text( + text = targetValue.resolveReference(), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.tertiary, + ) + } else { + TextShimmer( + style = TangemTheme.typography.body1, + text = stringResourceSafe(R.string.common_fee_error), + ) + } + } + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt index fe2157d2ef..c95c069d2d 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt @@ -7,4 +7,5 @@ internal data class YieldSupplyActiveContentUM( val availableBalance: TextReference, val providerTitle: TextReference, val subtitle: TextReference, + val subtitleLink: TextReference, ) \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt index 38365e52c6..f0d76c7bca 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt @@ -3,7 +3,6 @@ package com.tangem.features.yield.supply.impl.subcomponents.active.model import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer -import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList @@ -38,13 +37,11 @@ internal class YieldSupplyActiveModel @Inject constructor( }, ), providerTitle = resourceReference(R.string.yield_module_provider), - subtitle = combinedReference( - resourceReference( - id = R.string.yield_module_earn_sheet_provider_description, - formatArgs = wrappedList(cryptoCurrency.symbol, cryptoCurrency.symbol), - ), - resourceReference(R.string.common_read_more), + subtitle = resourceReference( + id = R.string.yield_module_earn_sheet_provider_description, + formatArgs = wrappedList(cryptoCurrency.symbol, cryptoCurrency.symbol), ), + subtitleLink = resourceReference(R.string.common_read_more), ), ) } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt index d0bb88752b..394a786540 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt @@ -13,6 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.withLink import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider @@ -90,11 +92,7 @@ private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM) { ) } SpacerH8() - Text( - text = state.subtitle.resolveReference(), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.tertiary, - ) + DescriptionText(state = state) SpacerH8() HorizontalDivider( thickness = 0.5.dp, @@ -115,6 +113,31 @@ private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM) { } } +@Composable +private fun DescriptionText(state: YieldSupplyActiveContentUM) { + val subtitle = annotatedReference { + append(state.subtitle.resolveReference()) + appendSpace() + withLink( + LinkAnnotation.Clickable( + tag = "LINK_TAG", + linkInteractionListener = {}, + ), + { + appendColored( + text = state.subtitleLink.resolveReference(), + color = TangemTheme.colors.icon.accent, + ) + }, + ) + } + Text( + text = subtitle.resolveAnnotatedReference(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + ) +} + @Composable private fun InfoRow(title: TextReference, info: TextReference) { Row( @@ -158,6 +181,7 @@ private class YieldSupplyActiveBottomSheetPreviewProvider : PreviewParameterProv R.string.yield_module_earn_sheet_provider_description, wrappedList("USDT", "USDT"), ), + subtitleLink = resourceReference(R.string.common_read_more), ), ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt new file mode 100644 index 0000000000..2e55b046d0 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt @@ -0,0 +1,67 @@ +package com.tangem.features.yield.supply.impl.subcomponents.feepolicy + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.ui.components.SecondaryButton +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle +import com.tangem.core.ui.decompose.ComposableModularContentComponent +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.features.yield.supply.impl.R +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM +import com.tangem.features.yield.supply.impl.subcomponents.feepolicy.ui.YieldSupplyFeePolicyContent +import kotlinx.coroutines.flow.StateFlow + +internal class YieldSupplyFeePolicyComponent( + private val appComponentContext: AppComponentContext, + private val params: Params, +) : ComposableModularContentComponent, AppComponentContext by appComponentContext { + + @Composable + override fun Title() { + TangemModalBottomSheetTitle( + startIconRes = R.drawable.ic_back_24, + onStartClick = params.callback::onBackClick, + ) + } + + @Composable + override fun Content(modifier: Modifier) { + val uiState by params.yieldSupplyActionUMFlow.collectAsStateWithLifecycle() + YieldSupplyFeePolicyContent( + yieldSupplyFeeUM = uiState.yieldSupplyFeeUM, + tokenSymbol = params.cryptoCurrency.symbol, + networkName = params.cryptoCurrency.network.name, + modifier = modifier, + ) + } + + @Composable + override fun Footer() { + SecondaryButton( + text = stringResourceSafe(R.string.common_got_it), + onClick = params.callback::onBackClick, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + ) + } + + data class Params( + val userWalletId: UserWalletId, + val cryptoCurrency: CryptoCurrency, + val yieldSupplyActionUMFlow: StateFlow, + val callback: ModelCallback, + ) + + interface ModelCallback { + fun onBackClick() + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt new file mode 100644 index 0000000000..b90e1b09b4 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt @@ -0,0 +1,127 @@ +package com.tangem.features.yield.supply.impl.subcomponents.feepolicy.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.SpacerH16 +import com.tangem.core.ui.components.SpacerH24 +import com.tangem.core.ui.components.SpacerH8 +import com.tangem.core.ui.components.containers.FooterContainer +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.yield.supply.impl.R +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.features.yield.supply.impl.common.ui.YieldSupplyFeeRow +import com.tangem.utils.StringsSigns +import kotlinx.collections.immutable.persistentListOf + +@Composable +internal fun YieldSupplyFeePolicyContent( + yieldSupplyFeeUM: YieldSupplyFeeUM, + tokenSymbol: String, + networkName: String, + modifier: Modifier = Modifier, +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .fillMaxWidth() + .padding( + start = 16.dp, + end = 16.dp, + top = 16.dp, + bottom = 8.dp, + ), + ) { + Text( + text = stringResourceSafe(R.string.yield_module_fee_policy_sheet_title), + style = TangemTheme.typography.h3, + color = TangemTheme.colors.text.primary1, + ) + SpacerH8() + Text( + text = stringResourceSafe(R.string.yield_module_fee_policy_sheet_description, tokenSymbol), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + modifier = Modifier.padding(horizontal = 16.dp), + ) + SpacerH24() + FooterContainer( + footer = resourceReference( + id = R.string.yield_module_fee_policy_sheet_current_fee_note, + formatArgs = wrappedList(networkName), + ), + paddingValues = PaddingValues( + top = 8.dp, + start = 12.dp, + end = 12.dp, + ), + ) { + val currentFee = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.currentNetworkFeeValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null + } + YieldSupplyFeeRow( + title = resourceReference(R.string.yield_module_fee_policy_sheet_current_fee_title), + value = currentFee, + ) + } + SpacerH16() + FooterContainer( + footer = resourceReference(R.string.yield_module_fee_policy_sheet_max_fee_note), + paddingValues = PaddingValues( + top = 8.dp, + start = 12.dp, + end = 12.dp, + ), + ) { + val maxFee = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.maxNetworkFeeValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null + } + YieldSupplyFeeRow( + title = resourceReference(R.string.yield_module_fee_policy_sheet_max_fee_title), + value = maxFee, + ) + } + } +} + +// region Preview +@Composable +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun YieldSupplyFeePolicyContent_Preview() { + TangemThemePreview { + YieldSupplyFeePolicyContent( + yieldSupplyFeeUM = YieldSupplyFeeUM.Content( + transactionDataList = persistentListOf(), + feeValue = stringReference("0.0001 ETH • \$1.45"), + maxNetworkFeeValue = stringReference("8.50 USDT • \$8.50"), + currentNetworkFeeValue = stringReference("1.45 USDT • \$1.45"), + ), + tokenSymbol = "USDT", + networkName = "Ethereum", + modifier = Modifier.background(TangemTheme.colors.background.primary), + + ) + } +} +// endregion \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt index 99e5075b5f..30fa2d47fe 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt @@ -24,8 +24,11 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.yield.supply.impl.R +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.ui.YieldSupplyActionContent import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.YieldSupplyStartEarningModel +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach internal class YieldSupplyStartEarningComponent( private val appComponentContext: AppComponentContext, @@ -34,6 +37,10 @@ internal class YieldSupplyStartEarningComponent( private val model: YieldSupplyStartEarningModel = getOrCreateModel(params = params) + init { + model.uiState.onEach(params.callback::onResult).launchIn(componentScope) + } + @Composable override fun Title() { TangemModalBottomSheetTitle( @@ -49,6 +56,7 @@ internal class YieldSupplyStartEarningComponent( YieldSupplyActionContent( yieldSupplyActionUM = state, + onFooterClick = params.callback::onFeePolicyClick, modifier = modifier, ) { Box( @@ -96,10 +104,12 @@ internal class YieldSupplyStartEarningComponent( data class Params( val userWalletId: UserWalletId, val cryptoCurrency: CryptoCurrency, + val yieldSupplyActionUM: YieldSupplyActionUM, val callback: ModelCallback, ) interface ModelCallback { + fun onResult(yieldSupplyActionUM: YieldSupplyActionUM) fun onBackClick() fun onFeePolicyClick() fun onTransactionSent() diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningEntryComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningEntryComponent.kt index d13e9293d2..77763ea8fc 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningEntryComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningEntryComponent.kt @@ -12,9 +12,9 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.decompose.navigation.inner.InnerRouter import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableModularContentComponent -import com.tangem.core.ui.decompose.getEmptyComposableModularContentComponent import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.features.yield.supply.impl.subcomponents.feepolicy.YieldSupplyFeePolicyComponent import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.YieldSupplyStartEarningEntryModel import com.tangem.features.yield.supply.impl.subcomponents.startearning.ui.YieldSupplyStartEarningBottomSheet @@ -67,12 +67,21 @@ internal class YieldSupplyStartEarningEntryComponent( route: YieldSupplyStartEarningRoute, factoryContext: AppComponentContext, ): ComposableModularContentComponent = when (route) { - YieldSupplyStartEarningRoute.FeePolicy -> getEmptyComposableModularContentComponent() // todo fee policy + YieldSupplyStartEarningRoute.FeePolicy -> YieldSupplyFeePolicyComponent( + appComponentContext = factoryContext, + params = YieldSupplyFeePolicyComponent.Params( + userWalletId = params.userWalletId, + cryptoCurrency = params.cryptoCurrency, + yieldSupplyActionUMFlow = model.uiState, + callback = model, + ), + ) YieldSupplyStartEarningRoute.Action -> YieldSupplyStartEarningComponent( appComponentContext = factoryContext, params = YieldSupplyStartEarningComponent.Params( userWalletId = params.userWalletId, cryptoCurrency = params.cryptoCurrency, + yieldSupplyActionUM = model.uiState.value, callback = model, ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt index c48e31cac8..1a9817b7af 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt @@ -4,10 +4,20 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router +import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.features.yield.supply.impl.R +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.features.yield.supply.impl.subcomponents.feepolicy.YieldSupplyFeePolicyComponent import com.tangem.features.yield.supply.impl.subcomponents.startearning.YieldSupplyStartEarningComponent import com.tangem.features.yield.supply.impl.subcomponents.startearning.YieldSupplyStartEarningEntryComponent import com.tangem.features.yield.supply.impl.subcomponents.startearning.YieldSupplyStartEarningRoute import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update import javax.inject.Inject @ModelScoped @@ -15,10 +25,30 @@ internal class YieldSupplyStartEarningEntryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, paramsContainer: ParamsContainer, -) : Model(), YieldSupplyStartEarningComponent.ModelCallback { +) : Model(), YieldSupplyStartEarningComponent.ModelCallback, YieldSupplyFeePolicyComponent.ModelCallback { private val params = paramsContainer.require() + val uiState: StateFlow + field: MutableStateFlow = MutableStateFlow( + YieldSupplyActionUM( + title = resourceReference(R.string.yield_module_start_earning), + subtitle = resourceReference( + R.string.yield_module_start_earning_sheet_description, + wrappedList(params.cryptoCurrency.symbol), + ), + footer = resourceReference(R.string.yield_module_start_earning_sheet_next_deposits), + footerLink = resourceReference(R.string.yield_module_start_earning_sheet_fee_policy), + currencyIconState = CryptoCurrencyToIconStateConverter().convert(params.cryptoCurrency), + yieldSupplyFeeUM = YieldSupplyFeeUM.Loading, + isPrimaryButtonEnabled = false, + ), + ) + + override fun onResult(yieldSupplyActionUM: YieldSupplyActionUM) { + uiState.update { yieldSupplyActionUM } + } + override fun onBackClick() { router.pop() } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 4119ea3edd..12b32f131f 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber import java.math.BigDecimal +import java.math.RoundingMode import javax.inject.Inject import kotlin.properties.Delegates @@ -79,10 +80,8 @@ internal class YieldSupplyStartEarningModel @Inject constructor( R.string.yield_module_start_earning_sheet_description, wrappedList(cryptoCurrency.symbol), ), - footer = combinedReference( - resourceReference(R.string.yield_module_start_earning_sheet_next_deposits), - resourceReference(R.string.yield_module_start_earning_sheet_fee_policy), - ), + footer = resourceReference(R.string.yield_module_start_earning_sheet_next_deposits), + footerLink = resourceReference(R.string.yield_module_start_earning_sheet_fee_policy), currencyIconState = CryptoCurrencyToIconStateConverter().convert(params.cryptoCurrency), yieldSupplyFeeUM = YieldSupplyFeeUM.Loading, isPrimaryButtonEnabled = false, @@ -120,12 +119,23 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } val crypto = feeSum.format { crypto(feeCryptoCurrencyStatusFlow.value.currency) } - val fiatFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> + val fiatFeeValue = feeCryptoCurrencyStatusFlow.value.value.fiatRate?.let { rate -> feeSum.multiply(rate) } val fiat = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + val tokenCryptoFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> + fiatFeeValue?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + } + val tokenCryptoFee = tokenCryptoFeeValue.format { crypto(cryptoCurrency) } + + val maxCryptoFee = MAX_NETWORK_FEE.format { crypto(cryptoCurrency) } + val maxFiatFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> + MAX_NETWORK_FEE.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + } + val maxFiatFee = maxFiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + uiState.update { if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) @@ -139,6 +149,16 @@ internal class YieldSupplyStartEarningModel @Inject constructor( stringReference(" $DOT "), stringReference(fiat), ), + currentNetworkFeeValue = combinedReference( + stringReference(tokenCryptoFee), + stringReference(" $DOT "), + stringReference(fiat), + ), + maxNetworkFeeValue = combinedReference( + stringReference(maxCryptoFee), + stringReference(" $DOT "), + stringReference(maxFiatFee), + ), ), ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt index 86ae2929ca..ccf5447946 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt @@ -49,6 +49,7 @@ internal class YieldSupplyStopEarningComponent( val state by model.uiState.collectAsStateWithLifecycle() YieldSupplyActionContent( yieldSupplyActionUM = state, + onFooterClick = model::onReadMoreClick, modifier = modifier, ) { Box( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index b4070199d3..b24eabaf2e 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -4,11 +4,9 @@ import arrow.core.getOrElse import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter -import com.tangem.core.ui.extensions.combinedReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.extensions.* import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format @@ -43,6 +41,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val yieldSupplyStopEarningUseCase: YieldSupplyStopEarningUseCase, + private val urlOpener: UrlOpener, ) : Model() { private val params: YieldSupplyStopEarningComponent.Params = paramsContainer.require() @@ -60,6 +59,9 @@ internal class YieldSupplyStopEarningModel @Inject constructor( ), ) + private val feeCryptoCurrencyStatus: CryptoCurrencyStatus + get() = feeCryptoCurrencyStatusFlow.value + private var appCurrency = AppCurrency.Default val uiState: StateFlow @@ -70,10 +72,8 @@ internal class YieldSupplyStopEarningModel @Inject constructor( id = R.string.yield_module_stop_earning_sheet_description, formatArgs = wrappedList(cryptoCurrency.symbol), ), - footer = combinedReference( - resourceReference(R.string.yield_module_stop_earning_sheet_fee_note), - resourceReference(R.string.common_read_more), - ), + footer = resourceReference(R.string.yield_module_stop_earning_sheet_fee_note), + footerLink = resourceReference(R.string.common_read_more), currencyIconState = CryptoCurrencyToIconStateConverter().convert(cryptoCurrency), yieldSupplyFeeUM = YieldSupplyFeeUM.Loading, isPrimaryButtonEnabled = false, @@ -87,6 +87,10 @@ internal class YieldSupplyStopEarningModel @Inject constructor( } } + fun onReadMoreClick() { + urlOpener.openUrl(READ_MORE_URL) + } + fun onClick() { val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return uiState.update { it.copy(isPrimaryButtonEnabled = false) } @@ -132,12 +136,13 @@ internal class YieldSupplyStopEarningModel @Inject constructor( network = cryptoCurrency.network, ).getOrNull() ?: return - val crypto = fee.normal.amount.value.format { crypto(feeCryptoCurrencyStatusFlow.value.currency) } - val fiatFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> - fee.normal.amount.value?.multiply(rate) - } + val feeCryptoValue = fee.normal.amount.value - val fiat = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + val feeFiatValue = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> + feeCryptoValue?.multiply(rate) + } + val cryptoFee = feeCryptoValue.format { crypto(feeCryptoCurrencyStatus.currency) } + val fiatFee = feeFiatValue.format { fiat(appCurrency.code, appCurrency.symbol) } uiState.update { if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { @@ -148,13 +153,19 @@ internal class YieldSupplyStopEarningModel @Inject constructor( yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = persistentListOf(exitTransitionData.copy(fee = fee.normal)), feeValue = combinedReference( - stringReference(crypto), + stringReference(cryptoFee), stringReference(" $DOT "), - stringReference(fiat), + stringReference(fiatFee), ), + currentNetworkFeeValue = TextReference.EMPTY, + maxNetworkFeeValue = TextReference.EMPTY, ), ) } } } + + private companion object { + const val READ_MORE_URL = "https://tangem.com" // todo yield supply replace with real link + } } \ No newline at end of file