Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-24 12:53:02 +05:00
parent 43d3520718
commit dbc325216e
9 changed files with 127 additions and 4 deletions

View file

@ -265,6 +265,11 @@ sealed class NotificationUM(val config: NotificationConfig) {
title = resourceReference(id = R.string.selling_insufficient_balance_alert_title), title = resourceReference(id = R.string.selling_insufficient_balance_alert_title),
subtitle = resourceReference(id = R.string.selling_insufficient_balance_alert_message), 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( open class Info(

View file

@ -29,6 +29,7 @@ data class ReceiveAddressModel(
data class TokenReceiveNotification( data class TokenReceiveNotification(
val title: Int, val title: Int,
val subtitle: Int, val subtitle: Int,
val isYieldSupplyNotification: Boolean = false,
) )
enum class Asset { enum class Asset {

View file

@ -95,6 +95,7 @@ internal class DefaultTokenReceiveComponent @AssistedInject constructor(
showMemoDisclaimer = model.params.config.showMemoDisclaimer, showMemoDisclaimer = model.params.config.showMemoDisclaimer,
fullName = model.params.config.cryptoCurrency.network.name, fullName = model.params.config.cryptoCurrency.network.name,
tokenName = model.getTokenName(), tokenName = model.getTokenName(),
currencyIconState = model.state.value.iconState,
), ),
) )
TokenReceiveRoutes.Warning -> TokenReceiveWarningComponent( TokenReceiveRoutes.Warning -> TokenReceiveWarningComponent(

View file

@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel 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.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource
import com.tangem.features.tokenreceive.entity.ReceiveAddress import com.tangem.features.tokenreceive.entity.ReceiveAddress
@ -38,6 +39,7 @@ internal class TokenReceiveAssetsComponent(
val callback: TokenReceiveAssetsModelCallback, val callback: TokenReceiveAssetsModelCallback,
val onDismiss: () -> Unit, val onDismiss: () -> Unit,
val showMemoDisclaimer: Boolean, val showMemoDisclaimer: Boolean,
val currencyIconState: CurrencyIconState,
val fullName: String, val fullName: String,
val tokenName: String, val tokenName: String,
) )

View file

@ -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.entity.ReceiveAddress.Type.Primary
import com.tangem.features.tokenreceive.ui.state.TokenReceiveUM import com.tangem.features.tokenreceive.ui.state.TokenReceiveUM
import com.tangem.utils.Provider import com.tangem.utils.Provider
import com.tangem.utils.extensions.addIf
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
@ -129,7 +130,12 @@ internal class TokenReceiveStateFactory(
tokenName: String, tokenName: String,
tokenReceiveNotification: List<TokenReceiveNotification>, tokenReceiveNotification: List<TokenReceiveNotification>,
): List<NotificationUM> { ): List<NotificationUM> {
val yieldSupplyNotification: TokenReceiveNotification? =
tokenReceiveNotification.firstOrNull { it.isYieldSupplyNotification }
return buildList { return buildList {
addIf(yieldSupplyNotification != null) {
NotificationUM.Warning.YieldSupplyIsActive(tokenName)
}
add( add(
NotificationUM.Info( NotificationUM.Info(
title = resourceReference( title = resourceReference(
@ -143,7 +149,7 @@ internal class TokenReceiveStateFactory(
iconTint = NotificationConfig.IconTint.Accent, iconTint = NotificationConfig.IconTint.Accent,
), ),
) )
tokenReceiveNotification.map { notification -> tokenReceiveNotification.filter { !it.isYieldSupplyNotification }.map { notification ->
add( add(
NotificationUM.Warning( NotificationUM.Warning(
title = resourceReference(notification.title), title = resourceReference(notification.title),

View file

@ -50,6 +50,8 @@ internal class TokenReceiveAssetsModel @Inject constructor(
showMemoDisclaimer = params.showMemoDisclaimer, showMemoDisclaimer = params.showMemoDisclaimer,
isEnsResultLoading = false, isEnsResultLoading = false,
notificationConfigs = params.notificationConfigs, notificationConfigs = params.notificationConfigs,
currencyIconState = params.currencyIconState,
network = params.tokenName,
), ),
) )

View file

@ -27,6 +27,7 @@ import androidx.compose.ui.util.fastForEach
import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.res.getStringSafe import com.tangem.core.res.getStringSafe
import com.tangem.core.ui.R 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.SpacerH12
import com.tangem.core.ui.components.SpacerH8 import com.tangem.core.ui.components.SpacerH8
import com.tangem.core.ui.components.SpacerW 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.atoms.text.TextEllipsis
import com.tangem.core.ui.components.buttons.small.TangemIconButton import com.tangem.core.ui.components.buttons.small.TangemIconButton
import com.tangem.core.ui.components.icons.identicon.IdentIcon 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.components.notifications.Notification
import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
@ -68,6 +71,7 @@ internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) {
Info( Info(
showMemoDisclaimer = assetsUM.showMemoDisclaimer, showMemoDisclaimer = assetsUM.showMemoDisclaimer,
notificationConfigs = assetsUM.notificationConfigs, notificationConfigs = assetsUM.notificationConfigs,
currencyIconState = assetsUM.currencyIconState,
) )
SpacerH12() SpacerH12()
@ -88,6 +92,7 @@ internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) {
@Composable @Composable
private fun Info( private fun Info(
currencyIconState: CurrencyIconState,
notificationConfigs: ImmutableList<NotificationUM>, notificationConfigs: ImmutableList<NotificationUM>,
showMemoDisclaimer: Boolean, showMemoDisclaimer: Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -109,9 +114,86 @@ private fun Info(
) )
} }
notificationConfigs.fastForEach { notificationConfigs.fastForEach { notificationConfig ->
key(it.hashCode()) { key(notificationConfig.hashCode()) {
Notification(config = it.config) // 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<Recei
onCopyClick = {}, onCopyClick = {},
onOpenQrCodeClick = {}, onOpenQrCodeClick = {},
isEnsResultLoading = true, isEnsResultLoading = true,
network = "USDT",
currencyIconState = CurrencyIconState.Locked,
) )
override val values: Sequence<ReceiveAssetsUM> override val values: Sequence<ReceiveAssetsUM>

View file

@ -1,6 +1,7 @@
package com.tangem.features.tokenreceive.ui.state package com.tangem.features.tokenreceive.ui.state
import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.features.tokenreceive.entity.ReceiveAddress import com.tangem.features.tokenreceive.entity.ReceiveAddress
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@ -10,5 +11,7 @@ internal data class ReceiveAssetsUM(
val onOpenQrCodeClick: (address: String) -> Unit, val onOpenQrCodeClick: (address: String) -> Unit,
val onCopyClick: (address: ReceiveAddress) -> Unit, val onCopyClick: (address: ReceiveAddress) -> Unit,
val isEnsResultLoading: Boolean, val isEnsResultLoading: Boolean,
val currencyIconState: CurrencyIconState,
val network: String,
val notificationConfigs: ImmutableList<NotificationUM>, val notificationConfigs: ImmutableList<NotificationUM>,
) )

View file

@ -38,6 +38,7 @@ import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.models.ReceiveAddressModel import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig 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.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network 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( return TokenDetailsBottomSheetConfig.Receive(
TokenReceiveConfig( TokenReceiveConfig(
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(), shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency, cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId, userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE, showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE,
tokenReceiveNotification = notifications,
receiveAddress = receiveAddresses, receiveAddress = receiveAddresses,
), ),
) )
@ -1139,6 +1153,11 @@ internal class TokenDetailsModel @Inject constructor(
needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus) needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
} }
private fun isActiveYieldSupply(): Boolean {
return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true
}
override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) { override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) {
bottomSheetNavigation.dismiss() bottomSheetNavigation.dismiss()
modelScope.launch { modelScope.launch {