diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 5f2e9a67e9..34d5e51c71 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -625,6 +625,8 @@
Le compte de destination est inactif. Envoyez %s ou plus pour activer le compte.
Pour créer un compte, envoyez des fonds à cette adresse
Le compte destinataire n\'a pas de Trustline pour l\'actif envoyé qu\'il tente d\'envoyer.
+ Obtenez 10 $ en BTC avec chaque wallet\nDépêchez-vous !
+ Black Friday : jusqu\'à 30% de réduction
Rejoignez maintenant
Partagez votre code et gagnez 5 USDT par vente. Votre ami bénéficie de 10 % de réduction.
Recevez des RÉCOMPENSES pour chaque ami !
diff --git a/core/ui/src/main/res/drawable/img_black_friday_promo.webp b/core/ui/src/main/res/drawable/img_black_friday_promo.webp
new file mode 100644
index 0000000000..18ad834359
Binary files /dev/null and b/core/ui/src/main/res/drawable/img_black_friday_promo.webp differ
diff --git a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt
index c8261d32ea..86c501406d 100644
--- a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt
+++ b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt
@@ -46,12 +46,17 @@ internal class DefaultPromoRepository(
!referralRepository.isReferralParticipant(userWalletId) && shouldShow
}.getOrDefault(false)
PromoId.Sepa -> {
- val isActive = getSepaPromoBanner()?.isActive ?: false
+ val isActive = getSepaPromoBanner()?.isActive == true
isActive && shouldShow
}
PromoId.VisaPresale -> {
- val isActive = getVisaPromoBanner()?.isActive ?: false
+ val isActive = getVisaPromoBanner()?.isActive == true
+
+ isActive && shouldShow
+ }
+ PromoId.BlackFriday -> {
+ val isActive = getBlackFridayPromoBanner()?.isActive == true
isActive && shouldShow
}
@@ -64,6 +69,7 @@ internal class DefaultPromoRepository(
PromoId.Referral -> flowOf(false)
PromoId.Sepa -> flowOf(false)
PromoId.VisaPresale -> flowOf(false)
+ PromoId.BlackFriday -> flowOf(false)
}
}
@@ -147,9 +153,18 @@ internal class DefaultPromoRepository(
}.getOrNull()
}
+ private suspend fun getBlackFridayPromoBanner(): PromoBanner? {
+ return runCatching(dispatchers.io) {
+ promoBannerConverter.convert(
+ tangemApi.getPromoBanner(BLACK_FRIDAY_NAME).getOrThrow(),
+ )
+ }.getOrNull()
+ }
+
private companion object {
const val SEPA_NAME = "sepa"
const val VISA_NAME = "visa-waitlist"
+ const val BLACK_FRIDAY_NAME = "black-friday"
const val STORIES_LOAD_DELAY = 1000L
}
}
\ No newline at end of file
diff --git a/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt b/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt
index 452445b991..764871ed95 100644
--- a/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt
+++ b/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt
@@ -29,4 +29,5 @@ enum class PromoId {
Referral,
Sepa,
VisaPresale,
+ BlackFriday,
}
\ No newline at end of file
diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt
index 396e1d8e90..d5b48a464e 100644
--- a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt
+++ b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt
@@ -31,6 +31,7 @@ class ShouldShowPromoWalletUseCase(
return when (promoId) {
PromoId.Referral,
PromoId.VisaPresale,
+ PromoId.BlackFriday,
-> true
PromoId.Sepa -> {
val walletFirstUsageDate = settingsRepository.getWalletFirstUsageDate()
diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt
index 1dcd4490f4..e0c863bf61 100644
--- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt
+++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt
@@ -7,9 +7,9 @@ sealed class PromoAnalyticsEvent(
event: String,
params: Map = mapOf(),
) : AnalyticsEvent(category = "Promotion", event = event, params = params) {
- class NoticePromotionBanner(
- source: AnalyticsParam.ScreensSources,
- program: Program,
+ data class NoticePromotionBanner(
+ private val source: AnalyticsParam.ScreensSources,
+ private val program: Program,
) : PromoAnalyticsEvent(
event = "Notice - Promotion Banner",
params = mapOf(
@@ -18,10 +18,10 @@ sealed class PromoAnalyticsEvent(
),
)
- class PromotionBannerClicked(
- source: AnalyticsParam.ScreensSources,
- program: Program,
- action: BannerAction,
+ data class PromotionBannerClicked(
+ private val source: AnalyticsParam.ScreensSources,
+ private val program: Program,
+ private val action: BannerAction,
) : PromoAnalyticsEvent(
event = "Promo Banner Clicked",
params = mapOf(
@@ -58,5 +58,6 @@ sealed class PromoAnalyticsEvent(
enum class Program(val programName: String) {
Empty("Empty"),
Sepa("Sepa"),
+ BlackFriday("Black Friday"),
}
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
index e078030757..e4f32d06b9 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
@@ -315,6 +315,11 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
action = PromotionBannerClicked.BannerAction.Closed,
)
PromoId.VisaPresale -> PromoAnalyticsEvent.VisaWaitlistPromoDismiss
+ PromoId.BlackFriday -> PromotionBannerClicked(
+ source = AnalyticsParam.ScreensSources.Main,
+ program = Program.BlackFriday,
+ action = PromotionBannerClicked.BannerAction.Closed,
+ )
},
)
@@ -352,6 +357,16 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
analyticsEventHandler.send(PromoAnalyticsEvent.VisaWaitlistPromoJoin)
urlOpener.openUrl(VISA_PROMO_LINK)
}
+ PromoId.BlackFriday -> {
+ analyticsEventHandler.send(
+ PromotionBannerClicked(
+ source = AnalyticsParam.ScreensSources.Main,
+ program = Program.BlackFriday,
+ action = PromotionBannerClicked.BannerAction.Clicked,
+ ),
+ )
+ urlOpener.openUrl(BLACK_FRIDAY_PROMO_LINK)
+ }
}
}
@@ -591,5 +606,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
const val VISA_PROMO_LINK = "https://tangem.com/en/cardwaitlist/?utm_source=tangem-app-banner" +
"&utm_medium=banner" +
"&utm_campaign=tangempaywaitlist"
+ const val BLACK_FRIDAY_PROMO_LINK = "https://tangem.com/en/pricing/" +
+ "?promocode=BF2025" +
+ "&utm_source=tangem-app-banner" +
+ "&utm_medium=banner" +
+ "&utm_campaign=BlackFriday2025"
}
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
index ab979acec8..b080fd487e 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
@@ -57,6 +57,10 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
source = AnalyticsParam.ScreensSources.Main,
program = Program.Sepa,
)
+ is WalletNotification.BlackFridayPromo -> NoticePromotionBanner(
+ source = AnalyticsParam.ScreensSources.Main,
+ program = Program.BlackFriday,
+ )
is WalletNotification.ReferralPromo -> MainScreen.ReferralPromo
is WalletNotification.VisaPresalePromo -> VisaWaitlistPromo
is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender]
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
index 5d05c74f9f..c2db89f8c8 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
@@ -103,6 +103,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
.distinctUntilChanged(),
shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Sepa)
.distinctUntilChanged(),
+ shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.BlackFriday)
+ .distinctUntilChanged(),
notificationsRepository.getShouldShowNotification(NotificationId.EnablePushesReminderNotification.key)
.distinctUntilChanged(),
getAccessCodeSkippedUseCase(userWallet.walletId).distinctUntilChanged(),
@@ -117,15 +119,23 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
val seedPhraseIssueStatus = array[3] as SeedPhraseNotificationsStatus
val shouldShowVisaPromo = array[4] as Boolean
val shouldShowSepaBanner = array[5] as Boolean
- val shouldShowEnablePushesReminderNotification = array[6] as Boolean
- val accessCodeSkipped = array[7] as Boolean
+ val shouldShowBlackFridayPromo = array[6] as Boolean
+ val shouldShowEnablePushesReminderNotification = array[7] as Boolean
+ val shouldAccessCodeSkipped = array[8] as Boolean
buildList {
addUsedOutdatedDataNotification(totalFiatBalance)
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
- addFinishWalletActivationNotification(userWallet, totalFiatBalance, clickIntents, accessCodeSkipped)
+ addFinishWalletActivationNotification(
+ userWallet = userWallet,
+ totalFiatBalance = totalFiatBalance,
+ clickIntents = clickIntents,
+ shouldAccessCodeSkipped = shouldAccessCodeSkipped,
+ )
+
+ addBlackFridayPromoNotification(clickIntents, shouldShowBlackFridayPromo)
addVisaPresalePromoNotification(clickIntents, shouldShowVisaPromo)
@@ -300,6 +310,19 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
)
}
+ private fun MutableList.addBlackFridayPromoNotification(
+ clickIntents: WalletClickIntents,
+ shouldShowPromo: Boolean,
+ ) {
+ addIf(
+ element = WalletNotification.BlackFridayPromo(
+ onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.BlackFriday) },
+ onClick = { clickIntents.onPromoClick(promoId = PromoId.BlackFriday) },
+ ),
+ condition = shouldShowPromo,
+ )
+ }
+
private suspend fun MutableList.addSepaPromoNotification(
userWallet: UserWallet,
flattenCurrencies: Lce>,
@@ -427,13 +450,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
userWallet: UserWallet,
totalFiatBalance: Lce,
clickIntents: WalletClickIntents,
- accessCodeSkipped: Boolean,
+ shouldAccessCodeSkipped: Boolean,
) {
if (userWallet !is UserWallet.Hot) return
val isBackupExists = userWallet.backedUp
val isAccessCodeRequired = userWallet.hotWalletId.authType == HotWalletId.AuthType.NoPassword &&
- !accessCodeSkipped
+ !shouldAccessCodeSkipped
val shouldShowFinishActivation = !isBackupExists || isAccessCodeRequired
val type = totalFiatBalance.fold(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
index 638da3f2e3..4553d72fc9 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
@@ -350,6 +350,23 @@ sealed class WalletNotification(val config: NotificationConfig) {
),
)
+ data class BlackFridayPromo(
+ val onCloseClick: () -> Unit,
+ val onClick: () -> Unit,
+ ) : WalletNotification(
+ config = NotificationConfig(
+ title = resourceReference(R.string.notification_black_friday_title),
+ subtitle = resourceReference(R.string.notification_black_friday_text),
+ iconResId = R.drawable.img_black_friday_promo,
+ onCloseClick = onCloseClick,
+ buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
+ text = resourceReference(R.string.common_claim),
+ onClick = onClick,
+ ),
+ iconSize = 54.dp,
+ ),
+ )
+
data class PushNotifications(
val onCloseClick: () -> Unit,
val onEnabledClick: () -> Unit,
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt
index 172ab84fbe..d8b52ad1ad 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt
@@ -22,29 +22,29 @@ internal fun LazyListScope.notifications(configs: ImmutableList
// TODO develop promo banner general component
- when (it) {
+ when (item) {
is WalletNotification.SwapPromo -> {
// Use it on new promo action
}
is WalletNotification.NoteMigration -> {
NoteMigrationNotification(
- config = it.config,
+ config = item.config,
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
)
}
is WalletNotification.FinishWalletActivation -> {
Notification(
- config = it.config,
+ config = item.config,
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
)
}
else -> {
Notification(
- config = it.config,
+ config = item.config,
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
- iconTint = when (it) {
+ iconTint = when (item) {
is WalletNotification.Critical -> TangemTheme.colors.icon.warning
is WalletNotification.Informational -> TangemTheme.colors.icon.accent
is WalletNotification.RateApp -> TangemTheme.colors.icon.attention
@@ -52,6 +52,7 @@ internal fun LazyListScope.notifications(configs: ImmutableList TangemTheme.colors.text.attention
else -> null
},
+ subtitleColor = TangemTheme.colors.text.secondary,
)
}
}
diff --git a/tangem-android-tools b/tangem-android-tools
index 92c1bfd312..3da4c865da 160000
--- a/tangem-android-tools
+++ b/tangem-android-tools
@@ -1 +1 @@
-Subproject commit 92c1bfd3123f0b2fd9e5a80b9d69bbc17a6e1160
+Subproject commit 3da4c865da5f2a61d5170357c60de4ddd8425815