Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-25 16:56:19 +05:00
parent 13c3b6d4e2
commit 2d2d157943
14 changed files with 105 additions and 8 deletions

View file

@ -2,6 +2,8 @@ package com.tangem.feature.wallet.child.wallet.model.intents
import arrow.core.getOrElse
import com.tangem.common.TangemBlogUrlBuilder
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.di.ModelScoped
@ -70,6 +72,8 @@ internal interface WalletWarningsClickIntents {
fun onClosePromoClick(promoId: PromoId)
fun onPromoClick(promoId: PromoId)
fun onSupportClick()
fun onNoteMigrationButtonClick(url: String)
@ -106,6 +110,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val urlOpener: UrlOpener,
private val tokensFeatureToggles: TokensFeatureToggles,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val appRouter: AppRouter,
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
override fun onAddBackupCardClick() {
@ -271,17 +276,32 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
override fun onClosePromoClick(promoId: PromoId) {
analyticsEventHandler.send(
TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
source = AnalyticsParam.ScreensSources.Main,
programName = TokenSwapPromoAnalyticsEvent.ProgramName.Empty, // Use it on new promo action
action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed,
),
if (promoId == PromoId.Referral) {
MainScreen.ReferralPromoButtonDismiss
} else {
TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
source = AnalyticsParam.ScreensSources.Main,
programName = TokenSwapPromoAnalyticsEvent.ProgramName.Empty, // Use it on new promo action
action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed,
)
},
)
modelScope.launch(dispatchers.main) {
shouldShowPromoWalletUseCase.neverToShow(promoId)
}
}
override fun onPromoClick(promoId: PromoId) {
if (promoId == PromoId.Referral) {
val userWallet = getSelectedUserWallet() ?: return
analyticsEventHandler.send(MainScreen.ReferralPromoButtonParticipate)
modelScope.launch {
shouldShowPromoWalletUseCase.neverToShow(promoId)
appRouter.push(AppRoute.ReferralProgram(userWalletId = userWallet.walletId))
}
}
}
override fun onSupportClick() {
val scanResponse = getSelectedUserWallet()?.scanResponse ?: return
val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return

View file

@ -137,5 +137,11 @@ sealed class WalletScreenAnalyticsEvent {
data object NoticeSeedPhraseSupportButtonUsed : MainScreen(event = "Button - Support Used")
data object NoticeSeedPhraseSupportButtonDeclined : MainScreen(event = "Button - Support Declined")
// region Referral Promo
data object ReferralPromo : MainScreen(event = "Referral Banner")
data object ReferralPromoButtonParticipate : MainScreen(event = "Button - Referral Participate")
data object ReferralPromoButtonDismiss : MainScreen(event = "Button - Referral Dismiss")
//endregion
}
}

View file

@ -53,6 +53,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
source = AnalyticsParam.ScreensSources.Main,
programName = ProgramName.Empty, // Use it on new promo action
)
is WalletNotification.ReferralPromo -> MainScreen.ReferralPromo
is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender]
is WalletNotification.Informational.NoAccount,
is WalletNotification.Warning.LowSignatures,

View file

@ -6,6 +6,8 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.models.StatusSource
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.CryptoCurrency
@ -34,6 +36,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
private val backupValidator: BackupValidator,
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
private val shouldShowPromoWalletUseCase: ShouldShowPromoWalletUseCase,
) {
@Suppress("MagicNumber", "MaximumLineLength")
@ -45,12 +48,15 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
flow2 = isReadyToShowRateAppUseCase(),
flow3 = isNeedToBackupUseCase(userWallet.walletId),
flow4 = seedPhraseNotificationUseCase(userWalletId = userWallet.walletId),
) { maybeTokenList, isReadyToShowRating, isNeedToBackup, seedPhraseIssueStatus ->
flow5 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Referral),
) { maybeTokenList, isReadyToShowRating, isNeedToBackup, seedPhraseIssueStatus, shouldShowReferralPromo ->
buildList {
addUsedOutdatedDataNotification(maybeTokenList)
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
addReferralPromoNotification(cardTypesResolver, clickIntents, shouldShowReferralPromo)
addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents)
addWarningNotifications(cardTypesResolver, maybeTokenList, isNeedToBackup, clickIntents)
@ -187,6 +193,20 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
.map(CryptoCurrencyStatus::currency)
}
private fun MutableList<WalletNotification>.addReferralPromoNotification(
cardTypesResolver: CardTypesResolver,
clickIntents: WalletClickIntents,
shouldShowPromo: Boolean,
) {
addIf(
element = WalletNotification.ReferralPromo(
onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.Referral) },
onClick = { clickIntents.onPromoClick(promoId = PromoId.Referral) },
),
condition = shouldShowPromo && cardTypesResolver.isTangemWallet(),
)
}
private fun MutableList<WalletNotification>.addWarningNotifications(
cardTypesResolver: CardTypesResolver,
tokenList: Lce<TokenListError, TokenList>,

View file

@ -254,4 +254,20 @@ sealed class WalletNotification(val config: NotificationConfig) {
iconResId = R.drawable.ic_error_sync_24,
),
)
data class ReferralPromo(
val onCloseClick: () -> Unit,
val onClick: () -> Unit,
) : WalletNotification(
config = NotificationConfig(
title = resourceReference(R.string.notification_referral_promo_title),
subtitle = resourceReference(R.string.notification_referral_promo_text),
iconResId = R.drawable.img_referral_promo,
onCloseClick = onCloseClick,
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.notification_referral_promo_button),
onClick = onClick,
),
),
)
}

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.notifications.NoteMigrationNotification
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.res.TangemTheme
@ -38,6 +39,11 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
Notification(
config = it.config,
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
iconSize = if (it is WalletNotification.ReferralPromo) {
54.dp
} else {
20.dp
},
iconTint = when (it) {
is WalletNotification.Critical -> TangemTheme.colors.icon.warning
is WalletNotification.Informational -> TangemTheme.colors.icon.accent