mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
feat: add unwatched episode count indicators to PosterItems and enhance media item data structure
This commit is contained in:
@@ -106,7 +106,8 @@ class JellyfinApiClient @Inject constructor(
|
||||
ItemFields.CHILD_COUNT,
|
||||
ItemFields.PARENT_ID,
|
||||
ItemFields.DATE_LAST_REFRESHED,
|
||||
ItemFields.OVERVIEW
|
||||
ItemFields.OVERVIEW,
|
||||
ItemFields.SEASON_USER_DATA
|
||||
)
|
||||
|
||||
suspend fun getLibraryContent(libraryId: UUID): List<BaseItemDto> {
|
||||
|
||||
@@ -3,6 +3,7 @@ package hu.bbara.purefin.common.ui
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -11,6 +12,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
@@ -23,6 +25,8 @@ import androidx.compose.ui.unit.sp
|
||||
import coil3.request.ImageRequest
|
||||
import hu.bbara.purefin.app.home.ui.PosterItem
|
||||
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
|
||||
import hu.bbara.purefin.common.ui.components.UnwatchedEpisodeIndicator
|
||||
import hu.bbara.purefin.common.ui.components.WatchStateIndicator
|
||||
import org.jellyfin.sdk.model.UUID
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
|
||||
@@ -62,17 +66,39 @@ fun PosterCard(
|
||||
modifier = Modifier
|
||||
.width(posterWidth)
|
||||
) {
|
||||
PurefinAsyncImage(
|
||||
model = imageRequest,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.aspectRatio(2f / 3f)
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.border(1.dp, scheme.outlineVariant.copy(alpha = 0.3f), RoundedCornerShape(14.dp))
|
||||
.background(scheme.surfaceVariant)
|
||||
.clickable(onClick = { openItem(item) }),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
Box() {
|
||||
PurefinAsyncImage(
|
||||
model = imageRequest,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.aspectRatio(2f / 3f)
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.border(1.dp, scheme.outlineVariant.copy(alpha = 0.3f), RoundedCornerShape(14.dp))
|
||||
.background(scheme.surfaceVariant)
|
||||
.clickable(onClick = { openItem(item) }),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
when (item.type) {
|
||||
BaseItemKind.MOVIE -> WatchStateIndicator(
|
||||
modifier = Modifier.align(Alignment.TopEnd)
|
||||
.padding(8.dp),
|
||||
watched = item.movie!!.watched,
|
||||
started = (item.movie.progress ?: 0.0) > 0
|
||||
)
|
||||
BaseItemKind.EPISODE -> WatchStateIndicator(
|
||||
modifier = Modifier.align(Alignment.TopEnd)
|
||||
.padding(8.dp),
|
||||
watched = item.episode!!.watched,
|
||||
started = (item.episode.progress ?: 0.0) > 0
|
||||
)
|
||||
BaseItemKind.SERIES -> UnwatchedEpisodeIndicator(
|
||||
modifier = Modifier.align(Alignment.TopEnd)
|
||||
.padding(8.dp),
|
||||
unwatchedCount = item.series!!.unwatchedEpisodeCount
|
||||
)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = item.title,
|
||||
color = scheme.onBackground,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package hu.bbara.purefin.common.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.unit.dp
|
||||
|
||||
@Composable
|
||||
fun UnwatchedEpisodeIndicator(
|
||||
unwatchedCount: Int,
|
||||
foregroundColor: Color = MaterialTheme.colorScheme.onPrimary,
|
||||
backgroundColor: Color = MaterialTheme.colorScheme.primary,
|
||||
size: Int = 24,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
if (unwatchedCount == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier
|
||||
.border(1.dp, backgroundColor.copy(alpha = 0.8f), CircleShape)
|
||||
.background(backgroundColor.copy(alpha = 0.8f), CircleShape)
|
||||
.size(size.dp)
|
||||
.clip(CircleShape)
|
||||
) {
|
||||
Text(
|
||||
text = unwatchedCount.toString(),
|
||||
color = foregroundColor.copy(alpha = 0.8f),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -364,6 +364,7 @@ class InMemoryMediaRepository @Inject constructor(
|
||||
itemId = this.id,
|
||||
type = ImageType.PRIMARY
|
||||
),
|
||||
unwatchedEpisodeCount = this.userData!!.unplayedItemCount!!,
|
||||
seasonCount = this.childCount!!,
|
||||
seasons = emptyList(),
|
||||
cast = emptyList()
|
||||
@@ -376,6 +377,7 @@ class InMemoryMediaRepository @Inject constructor(
|
||||
seriesId = this.seriesId!!,
|
||||
name = this.name ?: "Unknown",
|
||||
index = this.indexNumber!!,
|
||||
unwatchedEpisodeCount = this.userData!!.unplayedItemCount!!,
|
||||
episodeCount = this.childCount!!,
|
||||
episodes = emptyList()
|
||||
)
|
||||
|
||||
@@ -161,6 +161,7 @@ class RoomMediaLocalDataSource @Inject constructor(
|
||||
synopsis = synopsis,
|
||||
year = year,
|
||||
heroImageUrl = heroImageUrl,
|
||||
unwatchedEpisodeCount = unwatchedEpisodeCount,
|
||||
seasonCount = seasonCount
|
||||
)
|
||||
|
||||
@@ -169,6 +170,7 @@ class RoomMediaLocalDataSource @Inject constructor(
|
||||
seriesId = seriesId,
|
||||
name = name,
|
||||
index = index,
|
||||
unwatchedEpisodeCount = unwatchedEpisodeCount,
|
||||
episodeCount = episodeCount
|
||||
)
|
||||
|
||||
@@ -212,6 +214,7 @@ class RoomMediaLocalDataSource @Inject constructor(
|
||||
synopsis = synopsis,
|
||||
year = year,
|
||||
heroImageUrl = heroImageUrl,
|
||||
unwatchedEpisodeCount = unwatchedEpisodeCount,
|
||||
seasonCount = seasonCount,
|
||||
seasons = seasons,
|
||||
cast = cast
|
||||
@@ -222,6 +225,7 @@ class RoomMediaLocalDataSource @Inject constructor(
|
||||
seriesId = seriesId,
|
||||
name = name,
|
||||
index = index,
|
||||
unwatchedEpisodeCount = unwatchedEpisodeCount,
|
||||
episodeCount = episodeCount,
|
||||
episodes = episodes
|
||||
)
|
||||
|
||||
@@ -23,5 +23,6 @@ data class SeasonEntity(
|
||||
val seriesId: UUID,
|
||||
val name: String,
|
||||
val index: Int,
|
||||
val unwatchedEpisodeCount: Int,
|
||||
val episodeCount: Int
|
||||
)
|
||||
|
||||
@@ -12,5 +12,6 @@ data class SeriesEntity(
|
||||
val synopsis: String,
|
||||
val year: String,
|
||||
val heroImageUrl: String,
|
||||
val unwatchedEpisodeCount: Int,
|
||||
val seasonCount: Int
|
||||
)
|
||||
|
||||
@@ -7,6 +7,8 @@ data class Season(
|
||||
val seriesId: UUID,
|
||||
val name: String,
|
||||
val index: Int,
|
||||
val unwatchedEpisodeCount: Int,
|
||||
val episodeCount: Int,
|
||||
val episodes: List<Episode>
|
||||
)
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ data class Series(
|
||||
val synopsis: String,
|
||||
val year: String,
|
||||
val heroImageUrl: String,
|
||||
val unwatchedEpisodeCount: Int,
|
||||
val seasonCount: Int,
|
||||
val seasons: List<Season>,
|
||||
val cast: List<CastMember>
|
||||
)
|
||||
) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user