Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-14 11:50:47 +03:00
parent f1a4be49b3
commit ce948a71ae
51 changed files with 20 additions and 1186 deletions

View file

@ -13,8 +13,6 @@ android {
dependencies {
implementation(deps.androidx.datastore)
implementation(deps.jodatime)
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)

View file

@ -1,25 +1,17 @@
package com.tangem.data.promo
import com.tangem.data.promo.converters.PromoBannerConverter
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.PromoBannerStore
import com.tangem.datasource.local.promo.PromoStoriesStore
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.promo.PromoRepository
import com.tangem.domain.promo.models.PromoBanner
import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.promo.models.StoryContent
import com.tangem.feature.referral.domain.ReferralRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runCatching
import com.tangem.utils.coroutines.runSuspendCatching
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext
@ -29,84 +21,10 @@ internal class DefaultPromoRepository(
private val tangemApi: TangemTechApi,
private val appPreferencesStore: AppPreferencesStore,
private val promoStoriesStore: PromoStoriesStore,
private val promoBannerStore: PromoBannerStore,
private val dispatchers: CoroutineDispatcherProvider,
private val referralRepository: ReferralRepository,
) : PromoRepository {
private val storyContentConverter = StoryContentResponseConverter()
private val promoBannerConverter = PromoBannerConverter()
override fun isReadyToShowWalletPromo(userWalletId: UserWalletId, promoId: PromoId): Flow<Boolean> {
return appPreferencesStore.get(
key = PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name),
default = true,
)
.distinctUntilChanged()
.map { shouldShow ->
when (promoId) {
PromoId.Referral -> runSuspendCatching {
!referralRepository.isReferralParticipant(userWalletId) && shouldShow
}.getOrDefault(false)
PromoId.Sepa -> {
val isActive = getSepaPromoBanner()?.isActive == true
isActive && shouldShow
}
PromoId.VisaPresale -> {
val isActive = getVisaPromoBanner()?.isActive == true
isActive && shouldShow
}
PromoId.BlackFriday -> {
val isActive = getBlackFridayPromoBanner()?.isActive == true
isActive && shouldShow
}
PromoId.OnePlusOne -> {
val isActive = getOnePlusOnePromoBanner()?.isActive == true
isActive && shouldShow
}
PromoId.YieldPromo -> {
val isActive = getYieldPromoBanner(userWalletId)?.isActive == true
isActive && shouldShow
}
}
}
}
override fun isReadyToShowTokenPromo(promoId: PromoId): Flow<Boolean> {
return when (promoId) {
PromoId.Referral -> flowOf(false)
PromoId.Sepa -> flowOf(false)
PromoId.VisaPresale -> flowOf(false)
PromoId.BlackFriday -> flowOf(false)
PromoId.OnePlusOne -> flowOf(false)
PromoId.YieldPromo -> flowOf(false)
}
}
override suspend fun setNeverToShowWalletPromo(promoId: PromoId) {
appPreferencesStore.store(PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), false)
}
override suspend fun setNeverToShowTokenPromo(promoId: PromoId) {
appPreferencesStore.store(PreferencesKeys.getShouldShowPromoKey(promoId = promoId.name), false)
}
override suspend fun isMoonpayPromoActive(): Boolean {
val banner = runCatching(dispatchers.io) {
val response = promoBannerStore.getSyncOrNull(MOONPAY_NAME) ?: run {
val apiResponse = tangemApi.getPromoBanner(MOONPAY_NAME).getOrThrow()
promoBannerStore.store(MOONPAY_NAME, apiResponse)
apiResponse
}
promoBannerConverter.convert(response)
}.getOrNull()
return banner?.isActive == true
}
override fun getStoryById(id: String): Flow<StoryContent?> = isReadyToShowStories(id).mapLatest {
getStoryByIdSync(id = id, refresh = false)
@ -136,68 +54,21 @@ internal class DefaultPromoRepository(
}
override fun isReadyToShowStories(storyId: String): Flow<Boolean> {
return appPreferencesStore.get(getShouldShowStoriesKey(storyId), true)
return appPreferencesStore.get(PreferencesKeys.getShouldShowStoriesKey(storyId), true)
}
override suspend fun isReadyToShowStoriesSync(storyId: String): Boolean {
return appPreferencesStore.getSyncOrDefault(getShouldShowStoriesKey(storyId), true)
return appPreferencesStore.getSyncOrDefault(PreferencesKeys.getShouldShowStoriesKey(storyId), true)
}
override suspend fun setNeverToShowStories(storyId: String) {
appPreferencesStore.store(
key = getShouldShowStoriesKey(storyId),
key = PreferencesKeys.getShouldShowStoriesKey(storyId),
value = false,
)
}
private suspend fun getSepaPromoBanner(): PromoBanner? {
return runCatching(dispatchers.io) {
promoBannerConverter.convert(
tangemApi.getPromoBanner(SEPA_NAME).getOrThrow(),
)
}.getOrNull()
}
private suspend fun getVisaPromoBanner(): PromoBanner? {
return runCatching(dispatchers.io) {
promoBannerConverter.convert(
tangemApi.getPromoBanner(VISA_NAME).getOrThrow(),
)
}.getOrNull()
}
private suspend fun getBlackFridayPromoBanner(): PromoBanner? {
return runCatching(dispatchers.io) {
promoBannerConverter.convert(
tangemApi.getPromoBanner(BLACK_FRIDAY_NAME).getOrThrow(),
)
}.getOrNull()
}
private suspend fun getOnePlusOnePromoBanner(): PromoBanner? {
return runCatching(dispatchers.io) {
promoBannerConverter.convert(
tangemApi.getPromoBanner(ONE_PLUS_ONE_NAME).getOrThrow(),
)
}.getOrNull()
}
private suspend fun getYieldPromoBanner(userWalletId: UserWalletId): PromoBanner? {
return runCatching(dispatchers.io) {
val response = tangemApi.getPromoBannersV2(userWalletId.stringValue).getOrThrow()
val yieldPromotion = response.promotions.find { it.name == YIELD_PROMO_NAME }
?: return@runCatching null
promoBannerConverter.convert(yieldPromotion)
}.getOrNull()
}
private companion object {
const val SEPA_NAME = "sepa"
const val VISA_NAME = "visa-waitlist"
const val BLACK_FRIDAY_NAME = "black-friday"
const val MOONPAY_NAME = "moonpay"
const val ONE_PLUS_ONE_NAME = "one-plus-one"
const val YIELD_PROMO_NAME = "promo-yield"
const val STORIES_LOAD_DELAY = 1000L
}
}

View file

@ -1,24 +0,0 @@
package com.tangem.data.promo.converters
import com.tangem.datasource.api.promotion.models.PromoBannerResponse
import com.tangem.domain.promo.models.PromoBanner
import com.tangem.utils.converter.Converter
import org.joda.time.DateTime
class PromoBannerConverter : Converter<PromoBannerResponse, PromoBanner?> {
override fun convert(value: PromoBannerResponse): PromoBanner? {
val bannerState = value.bannerState ?: return null
return PromoBanner(
name = value.name,
bannerState = PromoBanner.BannerState(
status = bannerState.status,
link = bannerState.link,
timeline = PromoBanner.Timeline(
start = DateTime.parse(bannerState.timeline.start),
end = DateTime.parse(bannerState.timeline.end),
),
),
)
}
}

View file

@ -3,10 +3,8 @@ package com.tangem.data.promo.di
import com.tangem.data.promo.DefaultPromoRepository
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.promo.PromoBannerStore
import com.tangem.datasource.local.promo.PromoStoriesStore
import com.tangem.domain.promo.PromoRepository
import com.tangem.feature.referral.domain.ReferralRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
@ -24,17 +22,13 @@ internal object PromoDataModule {
tangemTechApi: TangemTechApi,
appPreferencesStore: AppPreferencesStore,
promoStoriesStore: PromoStoriesStore,
promoBannerStore: PromoBannerStore,
dispatchers: CoroutineDispatcherProvider,
referralRepository: ReferralRepository,
): PromoRepository {
return DefaultPromoRepository(
tangemApi = tangemTechApi,
appPreferencesStore = appPreferencesStore,
promoStoriesStore = promoStoriesStore,
dispatchers = dispatchers,
referralRepository = referralRepository,
promoBannerStore = promoBannerStore,
)
}
}