diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt
index b77078a426..c7c73612f8 100644
--- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt
+++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt
@@ -64,6 +64,7 @@ sealed class AnalyticsParam {
data object Send : ScreensSources("Send")
data object Intro : ScreensSources("Introduction")
data object MyWallets : ScreensSources("My Wallets")
+ data object Token : ScreensSources("Token")
}
sealed class TxSentFrom(val value: String) {
diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt
index e069422752..52b037fd6d 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt
@@ -53,14 +53,6 @@ object PreferencesKeys {
val LAST_SWAPPED_CRYPTOCURRENCY_ID_KEY by lazy { stringPreferencesKey(name = "lastSwappedCryptoCurrency") }
- val IS_WALLET_SWAP_PROMO_CHANGELLY_SHOW_KEY by lazy {
- booleanPreferencesKey(name = "isWalletSwapPromoChangellyShown")
- }
-
- val IS_TOKEN_SWAP_PROMO_CHANGELLY_SHOW_KEY by lazy {
- booleanPreferencesKey(name = "isTokenSwapPromoChangellyShown")
- }
-
val IS_WALLET_TRAVALA_PROMO_SHOWN_KEY by lazy {
booleanPreferencesKey(name = "isWalletTravalaPromoShown")
}
@@ -93,6 +85,14 @@ object PreferencesKeys {
val IS_WALLET_NAMES_MIGRATION_DONE_KEY by lazy { booleanPreferencesKey(name = "isWalletNamesMigrationDone") }
+ val IS_WALLET_SWAP_PROMO_OKX_SHOW_KEY by lazy {
+ booleanPreferencesKey(name = "isWalletSwapPromoOkxShown")
+ }
+
+ val IS_TOKEN_SWAP_PROMO_OKX_SHOW_KEY by lazy {
+ booleanPreferencesKey(name = "isTokenSwapPromoOkxShown")
+ }
+
fun getStart2CoinTOSAcceptedKey(region: String?) = booleanPreferencesKey(name = "start2Coin_tos_accepted_$region")
}
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 4772a93753..453bf3dd9b 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -550,6 +550,8 @@
Встречайте Tangem
Обменивайте, покупайте NFT, получайте займы и делайте вклады в более чем 100 различных децентрализованных сервисах
Поддержка Web 3.0
+ Обменивайте больше токенов по лучшим курсам прямо в вашем кошельке.
+ Новый провайдер обмена!
В сумму включено: \n• комиссия провайдера сервиса\n• комиссия сети за отправку %s от биржи обратно на адрес пользователя
В сумму включена комиссия провайдера сервиса.
Комиссии
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 6a39461d9a..c712fdab72 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -543,6 +543,8 @@
Meet Tangem
Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services
Web 3.0 Compatible
+ Exchange more tokens at better rates directly in your wallet.
+ New Swap Provider Available!
The amount includes:\n• service provider\'s fee\n• network fee for sending %s from the exchange back to the user\'s address.
The amount includes the service provider\'s fee.
Fees
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt
new file mode 100644
index 0000000000..9d6d403946
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt
@@ -0,0 +1,163 @@
+package com.tangem.core.ui.components.notifications
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.*
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import com.tangem.core.ui.R
+import com.tangem.core.ui.components.buttons.common.TangemButton
+import com.tangem.core.ui.components.buttons.common.TangemButtonColors
+import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
+import com.tangem.core.ui.extensions.resolveReference
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.res.LocalIsInDarkTheme
+import com.tangem.core.ui.res.TangemColorPalette.Dark6
+import com.tangem.core.ui.res.TangemColorPalette.Light4
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
+
+private val OxkPromoColor = Color(0xFFBCFF2F)
+
+@Composable
+fun OkxPromoNotification(config: NotificationConfig, modifier: Modifier = Modifier) {
+ Column(
+ modifier
+ .clip(TangemTheme.shapes.roundedCornersXMedium)
+ .background(Dark6),
+ ) {
+ Content(config = config)
+ Button(config = config)
+ }
+}
+
+@Composable
+private fun Content(config: NotificationConfig) {
+ Row {
+ Icon(
+ painter = rememberVectorPainter(image = ImageVector.vectorResource(id = R.drawable.img_okx_dex_logo)),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.constant,
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens.spacing12)
+ .align(Alignment.CenterVertically),
+ )
+ Column(
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
+ modifier = Modifier
+ .weight(1f)
+ .padding(TangemTheme.dimens.spacing12),
+ ) {
+ Text(
+ text = config.title.resolveReference(),
+ style = TangemTheme.typography.button,
+ color = OxkPromoColor,
+ )
+ Text(
+ text = config.subtitle.resolveReference(),
+ style = TangemTheme.typography.caption2,
+ color = TangemTheme.colors.text.constantWhite,
+ )
+ }
+ config.onCloseClick?.let {
+ Icon(
+ painter = rememberVectorPainter(
+ image = ImageVector.vectorResource(R.drawable.ic_close_24),
+ ),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.constant,
+ modifier =
+ Modifier
+ .padding(
+ top = TangemTheme.dimens.spacing8,
+ end = TangemTheme.dimens.spacing8,
+ )
+ .size(TangemTheme.dimens.size20)
+ .clickable(
+ interactionSource = remember { MutableInteractionSource() },
+ indication = rememberRipple(radius = TangemTheme.dimens.radius10),
+ onClick = it,
+ ),
+ )
+ }
+ }
+}
+
+@Composable
+private fun Button(config: NotificationConfig) {
+ val button = config.buttonsState as? NotificationConfig.ButtonsState.SecondaryButtonConfig
+
+ button?.let {
+ val isDarkMode = LocalIsInDarkTheme.current
+ TangemButton(
+ text = button.text.resolveReference(),
+ icon = TangemButtonIconPosition.Start(button.iconResId ?: R.drawable.ic_exchange_vertical_24),
+ onClick = button.onClick,
+ colors = TangemButtonColors(
+ backgroundColor = if (isDarkMode) Light4 else TangemTheme.colors.button.secondary,
+ contentColor = Dark6,
+ disabledBackgroundColor = TangemTheme.colors.button.disabled,
+ disabledContentColor = TangemTheme.colors.text.disabled,
+ ),
+ enabled = true,
+ showProgress = false,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(
+ start = TangemTheme.dimens.spacing12,
+ end = TangemTheme.dimens.spacing12,
+ bottom = TangemTheme.dimens.spacing12,
+ ),
+ )
+ }
+}
+
+// region Preview
+@Preview(widthDp = 360)
+@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun OkxPromoNotification_Preview(
+ @PreviewParameter(OkxPromoNotificationPreviewProvider::class) data: NotificationConfig,
+) {
+ TangemThemePreview {
+ OkxPromoNotification(data)
+ }
+}
+
+private class OkxPromoNotificationPreviewProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ NotificationConfig(
+ title = resourceReference(R.string.swap_promo_title),
+ subtitle = resourceReference(R.string.swap_promo_text),
+ iconResId = R.drawable.img_okx_dex_logo,
+ onCloseClick = {},
+ ),
+ NotificationConfig(
+ title = resourceReference(R.string.swap_promo_title),
+ subtitle = resourceReference(R.string.swap_promo_text),
+ iconResId = R.drawable.img_okx_dex_logo,
+ onCloseClick = {},
+ buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
+ text = resourceReference(R.string.token_swap_promotion_button),
+ onClick = {},
+ ),
+ ),
+ )
+}
+// endregion
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemColors.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemColors.kt
index 451207be18..2a78787608 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemColors.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemColors.kt
@@ -101,6 +101,7 @@ class TangemColors internal constructor(
private set
var attention by mutableStateOf(attention)
private set
+ var constant by mutableStateOf(constant)
fun update(other: Icon) {
primary1 = other.primary1
@@ -111,6 +112,7 @@ class TangemColors internal constructor(
accent = other.accent
warning = other.warning
attention = other.attention
+ constant = other.constant
}
}
diff --git a/core/ui/src/main/res/drawable/img_okx_dex_logo.xml b/core/ui/src/main/res/drawable/img_okx_dex_logo.xml
new file mode 100644
index 0000000000..3a4ba80759
--- /dev/null
+++ b/core/ui/src/main/res/drawable/img_okx_dex_logo.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 a92a4f5eb9..94a184fb73 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
@@ -32,8 +32,18 @@ internal class DefaultPromoRepository(
}.getOrNull()
}
+ override suspend fun getOkxPromoBanner(): PromoBanner? {
+ return runCatching(dispatchers.io) {
+ promoResponseConverter.convert(
+ tangemApi.getPromotionInfo(OKX)
+ .getOrThrow(),
+ )
+ }.getOrNull()
+ }
+
private companion object {
private const val CHANGELLY_NAME = "changelly"
private const val TRAVALA = "travala"
+ private const val OKX = "okx"
}
}
\ No newline at end of file
diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt
index 80ba44157d..ce6d3fa236 100644
--- a/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt
+++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt
@@ -1,8 +1,8 @@
package com.tangem.data.settings
import com.tangem.datasource.local.preferences.AppPreferencesStore
-import com.tangem.datasource.local.preferences.PreferencesKeys.IS_TOKEN_SWAP_PROMO_CHANGELLY_SHOW_KEY
-import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_SWAP_PROMO_CHANGELLY_SHOW_KEY
+import com.tangem.datasource.local.preferences.PreferencesKeys.IS_TOKEN_SWAP_PROMO_OKX_SHOW_KEY
+import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_SWAP_PROMO_OKX_SHOW_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_TRAVALA_PROMO_SHOWN_KEY
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.datasource.local.preferences.utils.store
@@ -16,23 +16,23 @@ class DefaultPromoSettingsRepository(
private val appPreferencesStore: AppPreferencesStore,
) : PromoSettingsRepository {
override fun isReadyToShowWalletSwapPromo(): Flow {
- return appPreferencesStore.get(IS_WALLET_SWAP_PROMO_CHANGELLY_SHOW_KEY, true)
+ return appPreferencesStore.get(IS_WALLET_SWAP_PROMO_OKX_SHOW_KEY, true)
}
override fun isReadyToShowTokenSwapPromo(): Flow {
- return appPreferencesStore.get(IS_TOKEN_SWAP_PROMO_CHANGELLY_SHOW_KEY, true)
+ return appPreferencesStore.get(IS_TOKEN_SWAP_PROMO_OKX_SHOW_KEY, true)
}
override suspend fun setNeverToShowWalletSwapPromo() {
appPreferencesStore.store(
- key = IS_WALLET_SWAP_PROMO_CHANGELLY_SHOW_KEY,
+ key = IS_WALLET_SWAP_PROMO_OKX_SHOW_KEY,
value = false,
)
}
override suspend fun setNeverToShowTokenSwapPromo() {
appPreferencesStore.store(
- key = IS_TOKEN_SWAP_PROMO_CHANGELLY_SHOW_KEY,
+ key = IS_TOKEN_SWAP_PROMO_OKX_SHOW_KEY,
value = false,
)
}
diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenSwapPromoAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenSwapPromoAnalyticsEvent.kt
index cc39985633..9e9156c366 100644
--- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenSwapPromoAnalyticsEvent.kt
+++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenSwapPromoAnalyticsEvent.kt
@@ -1,18 +1,43 @@
package com.tangem.domain.tokens.models.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam
sealed class TokenSwapPromoAnalyticsEvent(
event: String,
params: Map = mapOf(),
-) : AnalyticsEvent("Swap Promo", event, params, null) {
-
- object Close : TokenSwapPromoAnalyticsEvent(event = "Button - Close")
-
- class Exchange(
- token: String,
+) : AnalyticsEvent(category = "Promotion", event = event, params = params) {
+ class NoticePromotionBanner(
+ source: AnalyticsParam.ScreensSources,
+ programName: ProgramName,
) : TokenSwapPromoAnalyticsEvent(
- event = "Button - Exchange Now",
- params = mapOf("Token" to token),
+ event = "Notice - Promotion Banner",
+ params = mapOf(
+ AnalyticsParam.SOURCE to source.value,
+ "Program Name" to programName.name,
+ ),
)
+
+ class PromotionBannerClicked(
+ source: AnalyticsParam.ScreensSources,
+ programName: ProgramName,
+ action: BannerAction,
+ ) : TokenSwapPromoAnalyticsEvent(
+ event = "Promo Banner Clicked",
+ params = mapOf(
+ AnalyticsParam.SOURCE to source.value,
+ "Program Name" to programName.name,
+ "Action" to action.action,
+ ),
+ ) {
+ sealed class BannerAction(val action: String) {
+ data object Clicked : BannerAction(action = "Clicked")
+ data object Closed : BannerAction(action = "Closed")
+ }
+ }
+
+ enum class ProgramName {
+ Travala,
+ OKX,
+ }
}
\ No newline at end of file
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt
index eb7296acea..93ff397011 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt
@@ -84,7 +84,7 @@ class GetCurrencyWarningsUseCase(
): Flow {
val currency = currencyStatus.currency
val cryptoStatuses = operations.getCurrenciesStatusesSync()
- val promoBanner = promoRepository.getChangellyPromoBanner()
+ val promoBanner = promoRepository.getOkxPromoBanner()
return combine(
showSwapPromoTokenUseCase().conflate(),
flowOf(marketCryptoCurrencyRepository.isExchangeable(userWalletId, currency)).conflate(),
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt
index ed42ab1cfc..51ba0a57f9 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt
@@ -7,4 +7,6 @@ interface PromoRepository {
suspend fun getChangellyPromoBanner(): PromoBanner?
suspend fun getTravalaPromoBanner(): PromoBanner?
+
+ suspend fun getOkxPromoBanner(): PromoBanner?
}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt
index a69442cd51..878dc66047 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt
@@ -2,7 +2,9 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.analytics
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.tokens.model.CryptoCurrency
+import com.tangem.domain.tokens.models.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
@@ -35,12 +37,15 @@ internal class TokenDetailsNotificationsAnalyticsSender(
-> TokenDetailsAnalyticsEvent.Notice.NotEnoughFee(
currency = cryptoCurrency,
)
+ is TokenDetailsNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner(
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.OKX,
+ source = AnalyticsParam.ScreensSources.Token,
+ )
is TokenDetailsNotification.NetworksUnreachable,
is TokenDetailsNotification.ExistentialDeposit,
is TokenDetailsNotification.NetworksNoAccount,
is TokenDetailsNotification.TopUpWithoutReserve,
is TokenDetailsNotification.RentInfo,
- is TokenDetailsNotification.SwapPromo,
is TokenDetailsNotification.NetworkShutdown,
is TokenDetailsNotification.HederaAssociateWarning,
is TokenDetailsNotification.KoinosMana,
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/TokenDetailsNotification.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/TokenDetailsNotification.kt
index 950f24a218..a09065820b 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/TokenDetailsNotification.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/components/TokenDetailsNotification.kt
@@ -2,7 +2,10 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.componen
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.notifications.NotificationConfig
-import com.tangem.core.ui.extensions.*
+import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.networkIconResId
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.features.tokendetails.impl.R
@@ -45,16 +48,9 @@ internal sealed class TokenDetailsNotification(val config: NotificationConfig) {
val onCloseClick: () -> Unit,
) : TokenDetailsNotification(
config = NotificationConfig(
- title = resourceReference(
- id = R.string.token_swap_changelly_promotion_title,
- formatArgs = wrappedList("0%"),
- ),
- subtitle = resourceReference(
- id = R.string.token_swap_changelly_promotion_message,
- formatArgs = wrappedList("0%", startDateTime.dayOfMonth, endDateTime.dayOfMonth),
- ),
- iconResId = R.drawable.img_swap_promo,
- backgroundResId = R.drawable.img_swap_promo_green_banner_background,
+ title = resourceReference(id = R.string.swap_promo_title),
+ subtitle = resourceReference(id = R.string.swap_promo_text),
+ iconResId = R.drawable.img_okx_dex_logo,
onCloseClick = onCloseClick,
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
text = resourceReference(id = com.tangem.core.ui.R.string.token_swap_promotion_button),
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
index d9eb9ec18d..c24ca651d8 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt
@@ -32,7 +32,7 @@ import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBotto
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
import com.tangem.core.ui.components.notifications.Notification
-import com.tangem.core.ui.components.notifications.NotificationWithBackground
+import com.tangem.core.ui.components.notifications.OkxPromoNotification
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.components.transactions.txHistoryItems
import com.tangem.core.ui.event.EventEffect
@@ -111,7 +111,7 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) {
contentType = { it.config::class.java },
itemContent = {
if (it is TokenDetailsNotification.SwapPromo) {
- NotificationWithBackground(
+ OkxPromoNotification(
config = it.config,
modifier = itemModifier.animateItemPlacement(),
)
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
index d4e58af373..c2ff51d2d6 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
@@ -5,6 +5,7 @@ import androidx.paging.cachedIn
import arrow.core.getOrElse
import com.tangem.blockchain.common.address.AddressType
import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.core.deeplink.global.BuyCurrencyDeepLink
import com.tangem.core.ui.clipboard.ClipboardManager
@@ -709,14 +710,26 @@ internal class TokenDetailsViewModel @Inject constructor(
override fun onSwapPromoDismiss() {
viewModelScope.launch(dispatchers.main) {
shouldShowSwapPromoTokenUseCase.neverToShow()
- analyticsEventsHandler.send(TokenSwapPromoAnalyticsEvent.Close)
+ analyticsEventsHandler.send(
+ TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
+ source = AnalyticsParam.ScreensSources.Token,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.OKX,
+ action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed,
+ ),
+ )
}
}
override fun onSwapPromoClick() {
viewModelScope.launch(dispatchers.main) {
shouldShowSwapPromoTokenUseCase.neverToShow()
- analyticsEventsHandler.send(TokenSwapPromoAnalyticsEvent.Exchange(cryptoCurrency.symbol))
+ analyticsEventsHandler.send(
+ TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
+ source = AnalyticsParam.ScreensSources.Token,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.OKX,
+ action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Clicked,
+ ),
+ )
}
onSwapClick(ScenarioUnavailabilityReason.None)
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt
index f39a38511b..de6ddf8b1b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt
@@ -121,38 +121,4 @@ sealed class WalletScreenAnalyticsEvent {
data object DeleteWalletTapped : MainScreen(event = "Button - Delete Wallet Tapped")
}
-
- sealed class Promotion(
- event: String,
- params: Map = mapOf(),
- ) : AnalyticsEvent(category = "Promotion", event = event, params = params) {
- class NoticePromotionBanner(
- source: AnalyticsParam.ScreensSources,
- programName: String,
- ) : Promotion(
- event = "Notice - Promotion Banner",
- params = mapOf(
- AnalyticsParam.SOURCE to source.value,
- "Program Name" to programName,
- ),
- )
-
- class PromotionBannerClicked(
- source: AnalyticsParam.ScreensSources,
- programName: String,
- action: BannerAction,
- ) : Promotion(
- event = "Promo Banner Clicked",
- params = mapOf(
- AnalyticsParam.SOURCE to source.value,
- "Program Name" to programName,
- "Action" to action.action,
- ),
- ) {
- sealed class BannerAction(val action: String) {
- data object Clicked : BannerAction(action = "Clicked")
- data object Closed : BannerAction(action = "Closed")
- }
- }
- }
}
\ 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 59d4331387..398372e208 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
@@ -3,7 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics.utils
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
-import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
+import com.tangem.domain.tokens.models.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
@@ -46,16 +46,19 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
is WalletNotification.Informational.MissingAddresses -> MainScreen.MissingAddresses
is WalletNotification.RateApp -> MainScreen.HowDoYouLikeTangem
is WalletNotification.Critical.BackupError -> MainScreen.BackupError
- is WalletNotification.TravalaPromo -> WalletScreenAnalyticsEvent.Promotion.NoticePromotionBanner(
+ is WalletNotification.TravalaPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner(
source = AnalyticsParam.ScreensSources.Main,
- programName = "Travala",
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.Travala,
+ )
+ is WalletNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner(
+ source = AnalyticsParam.ScreensSources.Main,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.OKX,
)
is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender]
is WalletNotification.Informational.NoAccount,
is WalletNotification.Warning.LowSignatures,
is WalletNotification.Warning.SomeNetworksUnreachable,
is WalletNotification.Warning.NetworksUnreachable,
- is WalletNotification.SwapPromo,
-> null
}
}
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 a2adf6b292..b0513c7656 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
@@ -6,7 +6,7 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.promo.PromoBanner
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
-import com.tangem.domain.settings.ShouldShowTravalaPromoWalletUseCase
+import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase
import com.tangem.domain.tokens.GetTokenListUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.CryptoCurrency
@@ -34,7 +34,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
private val getTokenListUseCase: GetTokenListUseCase,
private val isDemoCardUseCase: IsDemoCardUseCase,
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
- private val shouldShowTravalaPromoWalletUseCase: ShouldShowTravalaPromoWalletUseCase,
+ private val shouldShowSwapPromoWalletUseCase: ShouldShowSwapPromoWalletUseCase,
private val promoRepository: PromoRepository,
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
private val backupValidator: BackupValidator,
@@ -45,18 +45,18 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow> {
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
- val travalaPromoFlow = flow { emit(promoRepository.getTravalaPromoBanner()) }
+ val promoFlow = flow { emit(promoRepository.getOkxPromoBanner()) }
return combine(
flow = getTokenListUseCase.launch(userWallet.walletId).conflate(),
flow2 = isReadyToShowRateAppUseCase().conflate(),
flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(),
- flow4 = shouldShowTravalaPromoWalletUseCase().conflate(),
- flow5 = travalaPromoFlow.conflate(),
- ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, shouldShowTravalaPromo, promoBanner ->
+ flow4 = shouldShowSwapPromoWalletUseCase().conflate(),
+ flow5 = promoFlow.conflate(),
+ ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, shouldShowPromo, promoBanner ->
readyForRateAppNotification = true
buildList {
- addTravalaPromoNotification(shouldShowTravalaPromo, promoBanner, clickIntents)
+ addSwapPromoNotification(shouldShowPromo, promoBanner, clickIntents)
addCriticalNotifications(userWallet)
@@ -69,18 +69,16 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
}
}
- private fun MutableList.addTravalaPromoNotification(
+ private fun MutableList.addSwapPromoNotification(
shouldShowPromo: Boolean,
promoBanner: PromoBanner?,
clickIntents: WalletClickIntents,
) {
promoBanner ?: return
- val promoNotification = WalletNotification.TravalaPromo(
+ val promoNotification = WalletNotification.SwapPromo(
startDateTime = promoBanner.bannerState.timeline.start,
endDateTime = promoBanner.bannerState.timeline.end,
- bannerLink = promoBanner.bannerState.link,
- onBookNowButtonClick = clickIntents::onTravalaPromoClick,
- onCloseClick = clickIntents::onCloseTravalaPromoClick,
+ onCloseClick = clickIntents::onCloseSwapPromoClick,
)
addIf(
element = promoNotification,
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 c34e986c29..4a3247b5e1 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
@@ -2,7 +2,10 @@ package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.notifications.NotificationConfig
-import com.tangem.core.ui.extensions.*
+import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.pluralReference
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.utils.DateTimeFormatters
import com.tangem.feature.wallet.impl.R
import org.joda.time.DateTime
@@ -205,16 +208,9 @@ sealed class WalletNotification(val config: NotificationConfig) {
val onCloseClick: () -> Unit,
) : WalletNotification(
config = NotificationConfig(
- title = resourceReference(
- id = R.string.main_swap_changelly_promotion_title,
- formatArgs = wrappedList("0%"),
- ),
- subtitle = resourceReference(
- id = R.string.main_swap_changelly_promotion_message,
- formatArgs = wrappedList("0%", startDateTime.dayOfMonth, endDateTime.dayOfMonth),
- ),
- iconResId = R.drawable.img_swap_promo,
- backgroundResId = R.drawable.img_swap_promo_green_banner_background,
+ title = resourceReference(id = R.string.swap_promo_title),
+ subtitle = resourceReference(id = R.string.swap_promo_text),
+ iconResId = R.drawable.img_okx_dex_logo,
onCloseClick = onCloseClick,
),
)
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 6b783e0eb0..08a341ebb7 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
@@ -5,7 +5,7 @@ import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.ui.Modifier
import com.tangem.core.ui.components.notifications.Notification
-import com.tangem.core.ui.components.notifications.NotificationWithBackground
+import com.tangem.core.ui.components.notifications.OkxPromoNotification
import com.tangem.core.ui.components.notifications.TravalaNotificationWithBackground
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
@@ -29,7 +29,7 @@ internal fun LazyListScope.notifications(configs: ImmutableList {
- NotificationWithBackground(
+ OkxPromoNotification(
config = it.config,
modifier = modifier.animateItemPlacement(),
)
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt
index 21982d8010..d2af11e81b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt
@@ -14,13 +14,13 @@ import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase
import com.tangem.domain.settings.ShouldShowTravalaPromoWalletUseCase
import com.tangem.domain.tokens.FetchTokenListUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
+import com.tangem.domain.tokens.models.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
import com.tangem.domain.wallets.models.UnlockWalletsError
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase
import com.tangem.feature.wallet.impl.R
-import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.domain.ScanCardToUnlockWalletClickHandler
@@ -214,6 +214,13 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
override fun onCloseSwapPromoClick() {
+ analyticsEventHandler.send(
+ TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
+ source = AnalyticsParam.ScreensSources.Main,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.OKX,
+ action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed,
+ ),
+ )
viewModelScope.launch(dispatchers.main) {
shouldShowSwapPromoWalletUseCase.neverToShow()
}
@@ -221,10 +228,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
override fun onTravalaPromoClick(link: String?) {
analyticsEventHandler.send(
- WalletScreenAnalyticsEvent.Promotion.PromotionBannerClicked(
+ TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
source = AnalyticsParam.ScreensSources.Main,
- programName = "Travala",
- action = WalletScreenAnalyticsEvent.Promotion.PromotionBannerClicked.BannerAction.Clicked,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.Travala,
+ action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Clicked,
),
)
link?.let {
@@ -236,10 +243,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
override fun onCloseTravalaPromoClick() {
analyticsEventHandler.send(
- WalletScreenAnalyticsEvent.Promotion.PromotionBannerClicked(
+ TokenSwapPromoAnalyticsEvent.PromotionBannerClicked(
source = AnalyticsParam.ScreensSources.Main,
- programName = "Travala",
- action = WalletScreenAnalyticsEvent.Promotion.PromotionBannerClicked.BannerAction.Closed,
+ programName = TokenSwapPromoAnalyticsEvent.ProgramName.Travala,
+ action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed,
),
)
viewModelScope.launch(dispatchers.main) {