Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-14 13:35:52 +03:00
parent f58a422765
commit c2e8cb82a7
39 changed files with 105 additions and 105 deletions

1
domain/stories/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,14 @@
plugins {
alias(deps.plugins.kotlin.jvm)
id("configuration")
}
dependencies {
implementation(projects.domain.models)
implementation(projects.domain.stories.models)
implementation(projects.domain.settings)
implementation(projects.domain.wallets.models)
implementation(deps.kotlin.coroutines)
implementation(deps.arrow.core)
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>NullableBooleanCheck:GetStoryContentUseCase.kt$GetStoryContentUseCase$isFCAAllowed(id).firstOrNull() ?: false</ID>
</CurrentIssues>
</SmellBaseline>

1
domain/stories/models/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,8 @@
plugins {
alias(deps.plugins.kotlin.jvm)
alias(deps.plugins.kotlin.serialization)
id("configuration")
}
dependencies {
}

View file

@ -0,0 +1,28 @@
package com.tangem.domain.stories.models
data class StoryContent(
val imageHost: String,
val story: Story,
) {
data class Story(
val id: String,
val title: String?,
val slides: List<StorySlide>,
)
data class StorySlide(
val id: String,
)
fun getImageUrls(): List<String> {
return story.slides.map { slide -> imageHost + slide.id + WEBP_EXTENSION }
}
private companion object {
const val WEBP_EXTENSION = ".webp"
}
}
enum class StoryContentIds(val id: String, val analyticType: String) {
STORY_FIRST_TIME_SWAP(id = "first-time-swap-v2", analyticType = "Swap"),
}

View file

@ -0,0 +1,55 @@
package com.tangem.domain.stories
import arrow.core.Either
import arrow.core.left
import arrow.core.right
import com.tangem.domain.stories.models.StoryContent
import com.tangem.domain.stories.models.StoryContentIds
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.models.needApplyFCARestrictions
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import kotlin.time.Duration.Companion.seconds
class GetStoryContentUseCase(
private val storiesRepository: StoriesRepository,
private val settingsRepository: SettingsRepository,
) {
operator fun invoke(id: String): Flow<Either<Throwable, StoryContent?>> {
return isFCAAllowed(id).transform { isAllowed ->
if (isAllowed) {
emitAll(
storiesRepository.getStoryById(id)
.map<StoryContent?, Either<Throwable, StoryContent?>> { it.right() }
.catch { emit(it.left()) }
.onEmpty { emit(null.right()) },
)
} else {
emit(null.right())
}
}
}
suspend fun invokeSync(id: String, refresh: Boolean = false): Either<Throwable, StoryContent?> = Either.catch {
val isFCAAllowed = isFCAAllowed(id).firstOrNull() ?: false
return@catch if (isFCAAllowed) {
storiesRepository.getStoryByIdSync(id, refresh)
} else {
null
}
}
@OptIn(FlowPreview::class)
private fun isFCAAllowed(id: String): Flow<Boolean> {
return if (id == StoryContentIds.STORY_FIRST_TIME_SWAP.id) {
settingsRepository.getUserCountryCode()
.filterNotNull()
.timeout(3.seconds)
.map { !it.needApplyFCARestrictions() }
.catch { emit(true) }
} else {
flowOf(true)
}
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.domain.stories
import kotlinx.coroutines.flow.Flow
class ShouldShowStoriesUseCase(private val storiesRepository: StoriesRepository) {
operator fun invoke(storyId: String): Flow<Boolean> = storiesRepository.isReadyToShowStories(storyId)
suspend fun invokeSync(storyId: String): Boolean = storiesRepository.isReadyToShowStoriesSync(storyId)
suspend fun neverToShow(storyId: String) = storiesRepository.setNeverToShowStories(storyId)
}

View file

@ -0,0 +1,19 @@
package com.tangem.domain.stories
import com.tangem.domain.stories.models.StoryContent
import kotlinx.coroutines.flow.Flow
interface StoriesRepository {
// region Stories
fun getStoryById(id: String): Flow<StoryContent?>
suspend fun getStoryByIdSync(id: String, refresh: Boolean): StoryContent?
fun isReadyToShowStories(storyId: String): Flow<Boolean>
suspend fun isReadyToShowStoriesSync(storyId: String): Boolean
suspend fun setNeverToShowStories(storyId: String)
// endregion
}