From dbc325216edf0b807f41b2927d579e48096201bc Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Sep 2025 12:53:02 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../common/ui/notifications/NotificationUM.kt | 5 ++ .../domain/models/TokenReceiveConfig.kt | 1 + .../component/DefaultTokenReceiveComponent.kt | 1 + .../component/TokenReceiveAssetsComponent.kt | 2 + .../entity/TokenReceiveStateFactory.kt | 8 +- .../model/TokenReceiveAssetsModel.kt | 2 + .../ui/TokenReceiveAssetsContent.kt | 90 ++++++++++++++++++- .../tokenreceive/ui/state/ReceiveAssetsUM.kt | 3 + .../tokendetails/model/TokenDetailsModel.kt | 19 ++++ 9 files changed, 127 insertions(+), 4 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt index 1d4ff127d6..fb40d6dc2a 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt @@ -265,6 +265,11 @@ sealed class NotificationUM(val config: NotificationConfig) { title = resourceReference(id = R.string.selling_insufficient_balance_alert_title), subtitle = resourceReference(id = R.string.selling_insufficient_balance_alert_message), ) + + data class YieldSupplyIsActive(val tokenName: String) : Warning( + title = resourceReference(id = R.string.yield_module_balance_info_sheet_title, wrappedList(tokenName)), + subtitle = resourceReference(id = R.string.yield_module_balance_info_sheet_subtitle), + ) } open class Info( diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/TokenReceiveConfig.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/TokenReceiveConfig.kt index d884942aeb..032940c3ee 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/TokenReceiveConfig.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/TokenReceiveConfig.kt @@ -29,6 +29,7 @@ data class ReceiveAddressModel( data class TokenReceiveNotification( val title: Int, val subtitle: Int, + val isYieldSupplyNotification: Boolean = false, ) enum class Asset { diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/DefaultTokenReceiveComponent.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/DefaultTokenReceiveComponent.kt index 20f139ff39..24d68dcfea 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/DefaultTokenReceiveComponent.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/DefaultTokenReceiveComponent.kt @@ -95,6 +95,7 @@ internal class DefaultTokenReceiveComponent @AssistedInject constructor( showMemoDisclaimer = model.params.config.showMemoDisclaimer, fullName = model.params.config.cryptoCurrency.network.name, tokenName = model.getTokenName(), + currencyIconState = model.state.value.iconState, ), ) TokenReceiveRoutes.Warning -> TokenReceiveWarningComponent( diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/TokenReceiveAssetsComponent.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/TokenReceiveAssetsComponent.kt index a292fe45db..eede7119b0 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/TokenReceiveAssetsComponent.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/component/TokenReceiveAssetsComponent.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource import com.tangem.features.tokenreceive.entity.ReceiveAddress @@ -38,6 +39,7 @@ internal class TokenReceiveAssetsComponent( val callback: TokenReceiveAssetsModelCallback, val onDismiss: () -> Unit, val showMemoDisclaimer: Boolean, + val currencyIconState: CurrencyIconState, val fullName: String, val tokenName: String, ) diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt index 5747409661..02595a5ca4 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt @@ -15,6 +15,7 @@ import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Ens import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Primary import com.tangem.features.tokenreceive.ui.state.TokenReceiveUM import com.tangem.utils.Provider +import com.tangem.utils.extensions.addIf import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList @@ -129,7 +130,12 @@ internal class TokenReceiveStateFactory( tokenName: String, tokenReceiveNotification: List, ): List { + val yieldSupplyNotification: TokenReceiveNotification? = + tokenReceiveNotification.firstOrNull { it.isYieldSupplyNotification } return buildList { + addIf(yieldSupplyNotification != null) { + NotificationUM.Warning.YieldSupplyIsActive(tokenName) + } add( NotificationUM.Info( title = resourceReference( @@ -143,7 +149,7 @@ internal class TokenReceiveStateFactory( iconTint = NotificationConfig.IconTint.Accent, ), ) - tokenReceiveNotification.map { notification -> + tokenReceiveNotification.filter { !it.isYieldSupplyNotification }.map { notification -> add( NotificationUM.Warning( title = resourceReference(notification.title), diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/model/TokenReceiveAssetsModel.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/model/TokenReceiveAssetsModel.kt index 134be8aa43..272cafc04e 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/model/TokenReceiveAssetsModel.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/model/TokenReceiveAssetsModel.kt @@ -50,6 +50,8 @@ internal class TokenReceiveAssetsModel @Inject constructor( showMemoDisclaimer = params.showMemoDisclaimer, isEnsResultLoading = false, notificationConfigs = params.notificationConfigs, + currencyIconState = params.currencyIconState, + network = params.tokenName, ), ) diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/TokenReceiveAssetsContent.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/TokenReceiveAssetsContent.kt index 22a746d2f2..c0416590a2 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/TokenReceiveAssetsContent.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/TokenReceiveAssetsContent.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.util.fastForEach import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.res.getStringSafe import com.tangem.core.ui.R +import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.SpacerH12 import com.tangem.core.ui.components.SpacerH8 import com.tangem.core.ui.components.SpacerW @@ -35,6 +36,8 @@ import com.tangem.core.ui.components.atoms.text.EllipsisText import com.tangem.core.ui.components.atoms.text.TextEllipsis import com.tangem.core.ui.components.buttons.small.TangemIconButton import com.tangem.core.ui.components.icons.identicon.IdentIcon +import com.tangem.core.ui.components.currency.icon.CurrencyIcon +import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference @@ -68,6 +71,7 @@ internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) { Info( showMemoDisclaimer = assetsUM.showMemoDisclaimer, notificationConfigs = assetsUM.notificationConfigs, + currencyIconState = assetsUM.currencyIconState, ) SpacerH12() @@ -88,6 +92,7 @@ internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) { @Composable private fun Info( + currencyIconState: CurrencyIconState, notificationConfigs: ImmutableList, showMemoDisclaimer: Boolean, modifier: Modifier = Modifier, @@ -109,9 +114,86 @@ private fun Info( ) } - notificationConfigs.fastForEach { - key(it.hashCode()) { - Notification(config = it.config) + notificationConfigs.fastForEach { notificationConfig -> + key(notificationConfig.hashCode()) { + // TODO remove after new design system + if (notificationConfig is NotificationUM.Warning.YieldSupplyIsActive) { + YieldSupplyDepositedWarning( + currencyIconState = currencyIconState, + title = stringResourceSafe( + R.string.yield_module_balance_info_sheet_title, + notificationConfig.tokenName, + ), + subtitle = stringResourceSafe(R.string.yield_module_balance_info_sheet_subtitle), + ) + } else { + Notification(config = notificationConfig.config) + } + } + } + } +} + +@Composable +private fun YieldSupplyDepositedWarning( + currencyIconState: CurrencyIconState, + title: String, + subtitle: String, + modifier: Modifier = Modifier, +) { + Surface( + modifier = modifier + .defaultMinSize(minHeight = TangemTheme.dimens.size44) + .fillMaxWidth(), + shape = TangemTheme.shapes.roundedCornersXMedium, + color = TangemTheme.colors.button.disabled, + ) { + Row( + modifier = Modifier + .padding(all = TangemTheme.dimens.spacing12), + ) { + Box( + modifier = Modifier + .height(22.dp) + .width(22.dp), + contentAlignment = Alignment.TopStart, + ) { + CurrencyIcon( + modifier = Modifier + .align(Alignment.TopStart) + .size(13.dp), + state = currencyIconState, + shouldDisplayNetwork = false, + iconSize = 13.dp, + ) + + Image( + modifier = Modifier + .background(TangemTheme.colors.background.tertiary, RoundedCornerShape(15.dp)) + .padding(1.dp) + .size(15.dp) + .align(Alignment.BottomEnd), + imageVector = ImageVector.vectorResource(R.drawable.img_aave_22), + contentDescription = null, + ) + } + + SpacerW(width = TangemTheme.dimens.spacing8) + + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.button, + ) + + SpacerH(height = TangemTheme.dimens.spacing2) + + Text( + text = subtitle, + color = TangemTheme.colors.text.tertiary, + style = TangemTheme.typography.caption2, + ) } } } @@ -340,6 +422,8 @@ private class TokenReceiveAssetsContentProvider : PreviewParameterProvider diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/state/ReceiveAssetsUM.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/state/ReceiveAssetsUM.kt index 9c8b118f36..b0a2fd2977 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/state/ReceiveAssetsUM.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/ui/state/ReceiveAssetsUM.kt @@ -1,6 +1,7 @@ package com.tangem.features.tokenreceive.ui.state import com.tangem.common.ui.notifications.NotificationUM +import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.features.tokenreceive.entity.ReceiveAddress import kotlinx.collections.immutable.ImmutableList @@ -10,5 +11,7 @@ internal data class ReceiveAssetsUM( val onOpenQrCodeClick: (address: String) -> Unit, val onCopyClick: (address: ReceiveAddress) -> Unit, val isEnsResultLoading: Boolean, + val currencyIconState: CurrencyIconState, + val network: String, val notificationConfigs: ImmutableList, ) \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index c1c4ef7ec8..ff704f39f3 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -38,6 +38,7 @@ import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.models.ReceiveAddressModel import com.tangem.domain.models.TokenReceiveConfig +import com.tangem.domain.models.TokenReceiveNotification import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network @@ -1086,12 +1087,25 @@ internal class TokenDetailsModel @Inject constructor( } } + val notifications = buildList { + if (isActiveYieldSupply()) { + add( + TokenReceiveNotification( + title = R.string.yield_module_balance_info_sheet_title, + subtitle = R.string.yield_module_balance_info_sheet_subtitle, + isYieldSupplyNotification = true, + ), + ) + } + } + return TokenDetailsBottomSheetConfig.Receive( TokenReceiveConfig( shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(), cryptoCurrency = cryptoCurrency, userWalletId = userWalletId, showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE, + tokenReceiveNotification = notifications, receiveAddress = receiveAddresses, ), ) @@ -1139,6 +1153,11 @@ internal class TokenDetailsModel @Inject constructor( needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus) } + private fun isActiveYieldSupply(): Boolean { + return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled && + cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true + } + override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) { bottomSheetNavigation.dismiss() modelScope.launch {