Refactor media models to use MediaUiModel for improved consistency and type safety

This commit is contained in:
2026-04-17 21:13:45 +02:00
parent 5a377fc428
commit 632dda52d6
27 changed files with 310 additions and 494 deletions

View File

@@ -10,7 +10,3 @@ kotlin {
}
jvmToolchain(11)
}
dependencies {
implementation(project(":core:model"))
}

View File

@@ -10,3 +10,7 @@ kotlin {
}
jvmToolchain(11)
}
dependencies {
implementation(project(":core:image"))
}

View File

@@ -0,0 +1,85 @@
package hu.bbara.purefin.core.ui.model
import hu.bbara.purefin.core.image.ArtworkKind
import hu.bbara.purefin.core.image.ImageUrlBuilder
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Series
import java.util.UUID
sealed interface MediaUiModel {
val id: UUID
val primaryText: String
val secondaryText: String
val description: String
val imageUrl: String
val progress: Float?
get() = null
val watched: Boolean
get() = false
}
class MovieUiModel: MediaUiModel {
override val id: UUID
override val primaryText: String
override val secondaryText: String
override val description: String
override val imageUrl: String
override val progress: Float?
constructor(movie: Movie) {
id = movie.id
primaryText = movie.title
secondaryText = movie.year
description = movie.synopsis
imageUrl = ImageUrlBuilder.finishImageUrl(
prefixImageUrl = movie.imageUrlPrefix,
artworkKind = ArtworkKind.PRIMARY
)
progress = (movie.progress?.toFloat() ?: 0f) / 100f
}
}
class SeriesUiModel : MediaUiModel {
override val id: UUID
override val primaryText: String
override val secondaryText: String
override val description: String
override val imageUrl: String
constructor(series: Series) {
id = series.id
primaryText = series.name
secondaryText = "${series.seasonCount} seasons"
description = series.synopsis
imageUrl = ImageUrlBuilder.finishImageUrl(
prefixImageUrl = series.imageUrlPrefix,
artworkKind = ArtworkKind.PRIMARY
)
}
}
class EpisodeUiModel : MediaUiModel {
override val id: UUID
override val primaryText: String
override val secondaryText: String
override val description: String
override val imageUrl: String
override val progress: Float?
val seriesId: UUID
val seasonId: UUID
constructor(episode: Episode) {
id = episode.id
primaryText = episode.title
secondaryText = episode.releaseDate
description = episode.synopsis
imageUrl = ImageUrlBuilder.finishImageUrl(
prefixImageUrl = episode.imageUrlPrefix,
artworkKind = ArtworkKind.PRIMARY
)
progress = (episode.progress?.toFloat() ?: 0f) / 100f
seriesId = episode.seriesId
seasonId = episode.seasonId
}
}

View File

@@ -30,7 +30,9 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import hu.bbara.purefin.core.model.MediaKind
import hu.bbara.purefin.ui.common.badge.UnwatchedEpisodeBadge
import hu.bbara.purefin.core.ui.model.EpisodeUiModel
import hu.bbara.purefin.core.ui.model.MediaUiModel
import hu.bbara.purefin.core.ui.model.MovieUiModel
import hu.bbara.purefin.ui.common.badge.WatchStateBadge
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
@@ -57,7 +59,7 @@ sealed interface PosterCardBadge {
@Composable
fun PosterCardContent(
model: PosterCardModel,
model: MediaUiModel,
onClick: () -> Unit,
modifier: Modifier = Modifier,
imageModifier: Modifier = Modifier,
@@ -108,36 +110,25 @@ fun PosterCardContent(
.clickable(onClick = onClick),
contentScale = ContentScale.Crop
)
when (val badge = model.badge) {
is PosterCardBadge.WatchState -> {
when (model) {
is MovieUiModel, is EpisodeUiModel -> {
WatchStateBadge(
size = indicatorSize,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(indicatorPadding),
watched = badge.watched,
started = badge.started
watched = model.watched,
started = (model.progress ?: 0f) > 0f
)
}
is PosterCardBadge.UnwatchedEpisodes -> {
UnwatchedEpisodeBadge(
size = indicatorSize,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(indicatorPadding),
unwatchedCount = badge.count
)
}
PosterCardBadge.None -> Unit
else -> Unit
}
}
Column(
modifier = Modifier.padding(top = 8.dp, start = 4.dp, end = 4.dp, bottom = 8.dp)
) {
Text(
text = model.title,
text = model.primaryText,
color = scheme.onBackground,
fontSize = 13.sp,
fontWeight = FontWeight.Medium,