From 7bdbd18cadf90b94937aec7a98a66d093f0ceec7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Apr 2025 16:42:18 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/di/domain/PromoDomainModule.kt | 8 ++--- .../local/preferences/PreferencesKeys.kt | 4 +++ .../data/promo/DefaultPromoRepository.kt | 29 ++++++++++++++----- .../tangem/domain/promo/models/PromoBanner.kt | 4 +++ .../tangem/domain/promo/PromoRepository.kt | 10 ++++--- .../promo/ShouldShowPromoTokenUseCase.kt | 11 +++++++ .../promo/ShouldShowPromoWalletUseCase.kt | 14 +++++++++ .../promo/ShouldShowSwapPromoTokenUseCase.kt | 10 ------- .../promo/ShouldShowSwapPromoWalletUseCase.kt | 10 ------- domain/tokens/models/build.gradle.kts | 1 + .../model/warnings/CryptoCurrencyWarning.kt | 2 ++ .../model/TokenDetailsClickIntents.kt | 5 ++-- .../tokendetails/model/TokenDetailsModel.kt | 13 +++++---- .../TokenDetailsNotificationConverter.kt | 6 ++-- .../intents/WalletWarningsClickIntents.kt | 11 +++---- 15 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoTokenUseCase.kt create mode 100644 domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt delete mode 100644 domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoTokenUseCase.kt delete mode 100644 domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoWalletUseCase.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt index 9e969c71de..8064273ab8 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt @@ -15,14 +15,14 @@ internal object PromoDomainModule { @Singleton fun provideShouldShowSwapPromoWalletUseCase( promoSettingsRepository: PromoRepository, - ): ShouldShowSwapPromoWalletUseCase { - return ShouldShowSwapPromoWalletUseCase(promoSettingsRepository) + ): ShouldShowPromoWalletUseCase { + return ShouldShowPromoWalletUseCase(promoSettingsRepository) } @Provides @Singleton - fun provideShouldShowSwapPromoTokenUseCase(promoRepository: PromoRepository): ShouldShowSwapPromoTokenUseCase { - return ShouldShowSwapPromoTokenUseCase(promoRepository) + fun provideShouldShowSwapPromoTokenUseCase(promoRepository: PromoRepository): ShouldShowPromoTokenUseCase { + return ShouldShowPromoTokenUseCase(promoRepository) } @Provides 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 50275788dd..e1cc610e17 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 @@ -123,8 +123,12 @@ object PreferencesKeys { val WALLETS_NFT_ENABLED_STATES_KEY by lazy { stringPreferencesKey(name = "walletsNftEnabledStates") } + // region Promo fun getShouldShowStoriesKey(storyId: String) = booleanPreferencesKey("shouldShowStories_$storyId") + fun getShouldShowPromoKey(promoId: String) = booleanPreferencesKey("shouldShowPromo_$promoId") + // endregion + // region Permission fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission") 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 5b14b75e9a..2c409f90fd 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 @@ -4,13 +4,16 @@ import com.tangem.data.promo.converters.StoryContentResponseConverter import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.PreferencesKeys.getShouldShowStoriesKey import com.tangem.datasource.local.preferences.utils.get import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.promo.PromoStoriesStore import com.tangem.domain.promo.PromoRepository +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.promo.models.StoryContent +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf @@ -27,20 +30,30 @@ internal class DefaultPromoRepository( private val storyContentConverter = StoryContentResponseConverter() - override fun isReadyToShowWalletSwapPromo(): Flow { - return flowOf(false) // Use it on new promo action + override fun isReadyToShowWalletPromo(userWalletId: UserWalletId, promoId: PromoId): Flow { + return appPreferencesStore.get( + key = PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), + default = true, + ) } - override fun isReadyToShowTokenSwapPromo(): Flow { - return flowOf(false) // Use it on new promo action + override fun isReadyToShowTokenPromo(promoId: PromoId): Flow { + return if (promoId == PromoId.Referral) { + flowOf(false) + } else { + appPreferencesStore.get( + PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), + default = false, + ) + } } - override suspend fun setNeverToShowWalletSwapPromo() { - // Use it on new promo action + override suspend fun setNeverToShowWalletPromo(promoId: PromoId) { + appPreferencesStore.store(PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), false) } - override suspend fun setNeverToShowTokenSwapPromo() { - // Use it on new promo action + override suspend fun setNeverToShowTokenPromo(promoId: PromoId) { + appPreferencesStore.store(PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), false) } override fun getStoryById(id: String): Flow = isReadyToShowStories(id).mapLatest { 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 42ecbd01d8..81f592f146 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 @@ -23,4 +23,8 @@ data class PromoBanner( private companion object { const val ACTIVE_STATUS = "active" } +} + +enum class PromoId { + Referral, } \ No newline at end of file diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/PromoRepository.kt b/domain/promo/src/main/java/com/tangem/domain/promo/PromoRepository.kt index 4db7b9bf87..88682deae2 100644 --- a/domain/promo/src/main/java/com/tangem/domain/promo/PromoRepository.kt +++ b/domain/promo/src/main/java/com/tangem/domain/promo/PromoRepository.kt @@ -1,18 +1,20 @@ package com.tangem.domain.promo +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.promo.models.StoryContent +import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow interface PromoRepository { // region Promo - fun isReadyToShowWalletSwapPromo(): Flow + fun isReadyToShowWalletPromo(userWalletId: UserWalletId, promoId: PromoId): Flow - fun isReadyToShowTokenSwapPromo(): Flow + fun isReadyToShowTokenPromo(promoId: PromoId): Flow - suspend fun setNeverToShowWalletSwapPromo() + suspend fun setNeverToShowWalletPromo(promoId: PromoId) - suspend fun setNeverToShowTokenSwapPromo() + suspend fun setNeverToShowTokenPromo(promoId: PromoId) // endregion // region Stories diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoTokenUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoTokenUseCase.kt new file mode 100644 index 0000000000..e6ad0e7580 --- /dev/null +++ b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoTokenUseCase.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.promo + +import com.tangem.domain.promo.models.PromoId +import kotlinx.coroutines.flow.Flow + +class ShouldShowPromoTokenUseCase(private val promoRepository: PromoRepository) { + + operator fun invoke(promoId: PromoId): Flow = promoRepository.isReadyToShowTokenPromo(promoId) + + suspend fun neverToShow(promoId: PromoId) = promoRepository.setNeverToShowTokenPromo(promoId) +} \ 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 new file mode 100644 index 0000000000..2a3a88329b --- /dev/null +++ b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt @@ -0,0 +1,14 @@ +package com.tangem.domain.promo + +import com.tangem.domain.promo.models.PromoId +import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow + +class ShouldShowPromoWalletUseCase(private val promoRepository: PromoRepository) { + + operator fun invoke(userWalletId: UserWalletId, promoId: PromoId): Flow { + return promoRepository.isReadyToShowWalletPromo(userWalletId, promoId) + } + + suspend fun neverToShow(promoId: PromoId) = promoRepository.setNeverToShowWalletPromo(promoId) +} \ No newline at end of file diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoTokenUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoTokenUseCase.kt deleted file mode 100644 index 9bd3a02d7f..0000000000 --- a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoTokenUseCase.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem.domain.promo - -import kotlinx.coroutines.flow.Flow - -class ShouldShowSwapPromoTokenUseCase(private val promoRepository: PromoRepository) { - - operator fun invoke(): Flow = promoRepository.isReadyToShowTokenSwapPromo() - - suspend fun neverToShow() = promoRepository.setNeverToShowTokenSwapPromo() -} \ No newline at end of file diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoWalletUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoWalletUseCase.kt deleted file mode 100644 index 5ed815ec9c..0000000000 --- a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowSwapPromoWalletUseCase.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem.domain.promo - -import kotlinx.coroutines.flow.Flow - -class ShouldShowSwapPromoWalletUseCase(private val promoRepository: PromoRepository) { - - operator fun invoke(): Flow = promoRepository.isReadyToShowWalletSwapPromo() - - suspend fun neverToShow() = promoRepository.setNeverToShowWalletSwapPromo() -} \ No newline at end of file diff --git a/domain/tokens/models/build.gradle.kts b/domain/tokens/models/build.gradle.kts index 9a926341a8..f618dc0f3f 100644 --- a/domain/tokens/models/build.gradle.kts +++ b/domain/tokens/models/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation(projects.domain.models) implementation(projects.domain.txhistory.models) implementation(projects.domain.staking.models) + implementation(projects.domain.promo.models) /** Other dependencies */ implementation(deps.kotlin.serialization) diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt index 623fbe5c1b..36cd8062dc 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt @@ -1,5 +1,6 @@ package com.tangem.domain.tokens.model.warnings +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.tokens.model.CryptoCurrency import org.joda.time.DateTime import java.math.BigDecimal @@ -42,6 +43,7 @@ sealed class CryptoCurrencyWarning { data class Rent(val rent: BigDecimal, val exemptionAmount: BigDecimal) : CryptoCurrencyWarning() data class SwapPromo( + val promoId: PromoId, val startDateTime: DateTime, val endDateTime: DateTime, ) : CryptoCurrencyWarning() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt index eeaaa1174a..c24e2e7736 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt @@ -2,6 +2,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.model import com.tangem.common.ui.bottomsheet.receive.AddressModel import com.tangem.core.ui.extensions.TextReference +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBalanceSegmentedButtonConfig @@ -49,9 +50,9 @@ interface TokenDetailsClickIntents { fun onGoToProviderClick(url: String) - fun onSwapPromoDismiss() + fun onSwapPromoDismiss(promoId: PromoId) - fun onSwapPromoClick() + fun onSwapPromoClick(promoId: PromoId) fun onGenerateExtendedKey() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 6ca825bee9..d76fff8838 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -35,7 +35,8 @@ import com.tangem.domain.card.NetworkHasDerivationUseCase import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.onramp.model.OnrampSource -import com.tangem.domain.promo.ShouldShowSwapPromoTokenUseCase +import com.tangem.domain.promo.ShouldShowPromoTokenUseCase +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.GetStakingAvailabilityUseCase import com.tangem.domain.staking.GetStakingEntryInfoUseCase @@ -101,7 +102,7 @@ internal class TokenDetailsModel @Inject constructor( private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, - private val shouldShowSwapPromoTokenUseCase: ShouldShowSwapPromoTokenUseCase, + private val shouldShowPromoTokenUseCase: ShouldShowPromoTokenUseCase, private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase, private val getExtendedPublicKeyForCurrencyUseCase: GetExtendedPublicKeyForCurrencyUseCase, private val getStakingEntryInfoUseCase: GetStakingEntryInfoUseCase, @@ -811,9 +812,9 @@ internal class TokenDetailsModel @Inject constructor( router.openUrl(url) } - override fun onSwapPromoDismiss() { + override fun onSwapPromoDismiss(promoId: PromoId) { modelScope.launch(dispatchers.main) { - shouldShowSwapPromoTokenUseCase.neverToShow() + shouldShowPromoTokenUseCase.neverToShow(promoId) analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Token, @@ -824,9 +825,9 @@ internal class TokenDetailsModel @Inject constructor( } } - override fun onSwapPromoClick() { + override fun onSwapPromoClick(promoId: PromoId) { modelScope.launch(dispatchers.main) { - shouldShowSwapPromoTokenUseCase.neverToShow() + shouldShowPromoTokenUseCase.neverToShow(promoId) analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Token, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt index 50b4710dd8..1413bff703 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt @@ -10,10 +10,10 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning import com.tangem.domain.tokens.model.warnings.HederaWarnings import com.tangem.domain.tokens.model.warnings.KaspaWarnings +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification.* -import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.converter.Converter import com.tangem.utils.extensions.removeBy @@ -98,8 +98,8 @@ internal class TokenDetailsNotificationConverter( is CryptoCurrencyWarning.SwapPromo -> SwapPromo( startDateTime = warning.startDateTime, endDateTime = warning.endDateTime, - onSwapClick = clickIntents::onSwapPromoClick, - onCloseClick = clickIntents::onSwapPromoDismiss, + onSwapClick = { clickIntents.onSwapPromoClick(warning.promoId) }, + onCloseClick = { clickIntents.onSwapPromoDismiss(warning.promoId) }, ) is CryptoCurrencyWarning.BeaconChainShutdown -> NetworkShutdown( title = resourceReference(R.string.warning_beacon_chain_retirement_title), 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 419db01ebc..2688e82b36 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 @@ -13,7 +13,8 @@ import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.promo.ShouldShowSwapPromoWalletUseCase +import com.tangem.domain.promo.ShouldShowPromoWalletUseCase +import com.tangem.domain.promo.models.PromoId import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.settings.NeverToSuggestRateAppUseCase @@ -67,7 +68,7 @@ internal interface WalletWarningsClickIntents { fun onCloseRateAppWarningClick() - fun onCloseSwapPromoClick() + fun onClosePromoClick(promoId: PromoId) fun onSupportClick() @@ -98,7 +99,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val reduxStateHolder: ReduxStateHolder, private val dispatchers: CoroutineDispatcherProvider, - private val shouldShowSwapPromoWalletUseCase: ShouldShowSwapPromoWalletUseCase, + private val shouldShowPromoWalletUseCase: ShouldShowPromoWalletUseCase, private val getCardInfoUseCase: GetCardInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase, @@ -268,7 +269,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( } } - override fun onCloseSwapPromoClick() { + override fun onClosePromoClick(promoId: PromoId) { analyticsEventHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Main, @@ -277,7 +278,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( ), ) modelScope.launch(dispatchers.main) { - shouldShowSwapPromoWalletUseCase.neverToShow() + shouldShowPromoWalletUseCase.neverToShow(promoId) } }