Updated on 2026-08-14

This commit is contained in:
Tangem 2025-11-27 12:26:54 +02:00
parent a8864541bc
commit 21be815a03
12 changed files with 97 additions and 1 deletions

View file

@ -1420,9 +1420,14 @@
<string name="tangempay_onboarding_security_description">あなたの住所や資産を開示することなく、個別の支払い用アカウントが作成されます。</string>
<string name="tangempay_onboarding_security_title">他に類を見ないプライバシー</string>
<string name="tangempay_onboarding_title">無料のTangem Payカードを数分でゲットしましょう</string>
<string name="tangempay_payment_account">支払いアカウント</string>
<string name="tangempay_payment_account_sync_needed">支払いアカウントの同期が必要です</string>
<string name="tangempay_service_unavailable_description">技術的な問題を修正しています。後でもう一度お試しください。</string>
<string name="tangempay_service_unavailable_title">サービスは一時的に利用できません</string>
<string name="tangempay_service_unreachable_try_later">現在サービスに接続できません。後ほどもう一度お試しください。</string>
<string name="tangempay_temporarily_unavailable">Tangem Payは一時的に利用できません</string>
<string name="tangempay_title">Tangem Pay</string>
<string name="tangempay_use_tangem_device_to_restore_payment_account">カードまたはリングを使用して、支払いアカウントへのアクセスを復元してください。</string>
<string name="this_is_my_wallet_title">これは私のウォレットです</string>
<string name="toast_balances_hidden">残高非表示</string>
<string name="toast_balances_shown">残高表示</string>

View file

@ -139,10 +139,17 @@
<string name="balance_hidden_title">Balances are hidden</string>
<string name="beta_mode_warning_message">According to the blockchain developers, Kaspa tokens are currently in beta. Stay tuned for updates!</string>
<string name="beta_mode_warning_title">Beta Mode</string>
<string name="biometric_disabled_warning_description">Biometrics are turned off on your device, so you cant use them to unlock your wallets. Enable biometrics in your device settings to use this method again.</string>
<string name="biometric_disabled_warning_title">Biometric authentication disabled</string>
<string name="biometric_lockout_permanent_warning_description">Please scan the card or ring</string>
<string name="biometric_lockout_permanent_warning_description_2">Youve reached the limit of biometric attempts. Please unlock your wallet with a device tap or enter your access code.</string>
<string name="biometric_lockout_permanent_warning_title">Biometric authentication locked</string>
<string name="biometric_lockout_warning_description">Please try again in 30 seconds or scan the card or ring</string>
<string name="biometric_lockout_warning_description_2">Biometric login is temporarily locked. Please try again in 30 seconds, or unlock your wallet with a device tap or access code.</string>
<string name="biometric_lockout_warning_title">Too many attempts</string>
<string name="biometric_unavailable_warning">You have disabled biometric authentication on your phone and will not be able to save wallets in the app. To save wallets, please enable the biometric authentication function in your phone settings.</string>
<string name="biometric_updated_warning_description">Biometrics on your device have been updated. Please select your wallet and enter its access code to enable biometric login again.</string>
<string name="biometric_updated_warning_title">Attention required</string>
<string name="bitcoin_promo_activation_error">An error occurred while processing your promo code. Please try again later.</string>
<string name="bitcoin_promo_activation_error_title">Activation error</string>
<string name="bitcoin_promo_activation_success">Your promo code was successfully activated. The reward will be credited to your Bitcoin account within 14 days.</string>
@ -835,6 +842,8 @@
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
<string name="no_account_send_to_create">To create account send funds to this address</string>
<string name="no_trustline_xlm_asset">The destination account does not have a trustline for the asset being sent.</string>
<string name="notification_black_friday_text">Plus rewards in BTC per set.\nHurry up!</string>
<string name="notification_black_friday_title">Black Friday: up to 25% OFF</string>
<string name="notification_referral_promo_button">Join Now</string>
<string name="notification_referral_promo_text">Share your code - earn 5 USDT per sale. Your friend gets 10% OFF.</string>
<string name="notification_referral_promo_title">Get REWARDS for every friend!</string>
@ -1445,9 +1454,14 @@
<string name="tangempay_onboarding_security_description">A separate payment account will be created without disclosing your addresses and assets</string>
<string name="tangempay_onboarding_security_title">Unrivaled privacy</string>
<string name="tangempay_onboarding_title">Get your free Tangem Pay Card in minutes</string>
<string name="tangempay_payment_account">Payment account</string>
<string name="tangempay_payment_account_sync_needed">Payment account sync needed</string>
<string name="tangempay_service_unavailable_description">Were fixing a technical issue. Please try again later.</string>
<string name="tangempay_service_unavailable_title">Service temporarily unavailable</string>
<string name="tangempay_service_unreachable_try_later">The service is currently unreachable. Please try again later.</string>
<string name="tangempay_temporarily_unavailable">Tangem Pay is temporarily unavailable</string>
<string name="tangempay_title">Tangem Pay</string>
<string name="tangempay_use_tangem_device_to_restore_payment_account">Use your card or ring to restore access to your payment account</string>
<string name="this_is_my_wallet_title">This is my wallet</string>
<string name="toast_balances_hidden">Balances hidden</string>
<string name="toast_balances_shown">Balances shown</string>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -54,6 +54,11 @@ internal class DefaultPromoRepository(
PromoId.VisaPresale -> {
val isActive = getVisaPromoBanner()?.isActive ?: false
isActive && shouldShow
}
PromoId.BlackFriday -> {
val isActive = getBlackFridayPromoBanner()?.isActive ?: false
isActive && shouldShow
}
}
@ -65,6 +70,7 @@ internal class DefaultPromoRepository(
PromoId.Referral -> flowOf(false)
PromoId.Sepa -> flowOf(false)
PromoId.VisaPresale -> flowOf(false)
PromoId.BlackFriday -> flowOf(false)
}
}
@ -148,9 +154,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
}
}

View file

@ -29,4 +29,5 @@ enum class PromoId {
Referral,
Sepa,
VisaPresale,
BlackFriday,
}

View file

@ -31,6 +31,7 @@ class ShouldShowPromoWalletUseCase(
return when (promoId) {
PromoId.Referral,
PromoId.VisaPresale,
PromoId.BlackFriday,
-> true
PromoId.Sepa -> {
val walletFirstUsageDate = settingsRepository.getWalletFirstUsageDate()

View file

@ -58,5 +58,6 @@ sealed class PromoAnalyticsEvent(
enum class Program(val programName: String) {
Empty("Empty"),
Sepa("Sepa"),
BlackFriday("Black Friday"),
}
}

View file

@ -335,6 +335,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,
)
},
)
@ -372,6 +377,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)
}
}
}
@ -587,5 +602,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"
}
}

View file

@ -58,6 +58,10 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
source = AnalyticsParam.ScreensSources.Main,
program = Program.Sepa,
)
is WalletNotification.BlackFridayPromo -> PromoAnalyticsEvent.NoticePromotionBanner(
source = AnalyticsParam.ScreensSources.Main,
program = Program.BlackFriday,
)
is WalletNotification.ReferralPromo -> MainScreen.ReferralPromo
is WalletNotification.VisaPresalePromo -> PromoAnalyticsEvent.VisaWaitlistPromo
is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender]

View file

@ -97,6 +97,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
seedPhraseNotificationUseCase(userWalletId = userWallet.walletId),
shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.VisaPresale),
shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Sepa),
shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.BlackFriday),
notificationsRepository.getShouldShowNotification(NotificationId.EnablePushesReminderNotification.key),
) { array -> array }
.combine(tokenListFlow()) { array, any: Any -> arrayOf(any).plus(elements = array) }
@ -109,7 +110,8 @@ 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 shouldShowBlackFridayPromo = array[6] as Boolean
val shouldShowEnablePushesReminderNotification = array[7] as Boolean
buildList {
addUsedOutdatedDataNotification(totalFiatBalance)
@ -118,6 +120,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
addFinishWalletActivationNotification(userWallet, totalFiatBalance, clickIntents)
addBlackFridayPromoNotification(clickIntents, shouldShowBlackFridayPromo)
addVisaPresalePromoNotification(clickIntents, shouldShowVisaPromo)
addSepaPromoNotification(userWallet, clickIntents, shouldShowSepaBanner)
@ -286,6 +290,19 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
)
}
private fun MutableList<WalletNotification>.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<WalletNotification>.addSepaPromoNotification(
userWallet: UserWallet,
clickIntents: WalletClickIntents,

View file

@ -332,6 +332,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,

View file

@ -52,6 +52,7 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
is WalletNotification.UsedOutdatedData -> TangemTheme.colors.text.attention
else -> null
},
subtitleColor = TangemTheme.colors.text.secondary,
)
}
}