Show year for cards

This commit is contained in:
Damontecres 2026-01-06 18:27:27 -05:00
parent d454cf0e3d
commit d175e3f471
No known key found for this signature in database
4 changed files with 48 additions and 9 deletions

View file

@ -12,12 +12,15 @@ import com.github.damontecres.wholphin.api.seerr.model.TvResult
import com.github.damontecres.wholphin.api.seerr.model.TvTvIdRatingsGet200Response import com.github.damontecres.wholphin.api.seerr.model.TvTvIdRatingsGet200Response
import com.github.damontecres.wholphin.services.SeerrSearchResult import com.github.damontecres.wholphin.services.SeerrSearchResult
import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.toLocalDate
import com.github.damontecres.wholphin.util.LocalDateSerializer
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.serializer.UUIDSerializer import org.jellyfin.sdk.model.serializer.UUIDSerializer
import org.jellyfin.sdk.model.serializer.toUUIDOrNull import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import java.time.LocalDate
import java.util.UUID import java.util.UUID
@Serializable @Serializable
@ -73,7 +76,7 @@ data class DiscoverItem(
val subtitle: String?, val subtitle: String?,
val overview: String?, val overview: String?,
val availability: SeerrAvailability, val availability: SeerrAvailability,
val releaseDate: String?, @Serializable(LocalDateSerializer::class) val releaseDate: LocalDate?,
val posterPath: String?, val posterPath: String?,
val backdropPath: String?, val backdropPath: String?,
val jellyfinItemId: UUID?, val jellyfinItemId: UUID?,
@ -107,7 +110,7 @@ data class DiscoverItem(
subtitle = null, subtitle = null,
overview = movie.overview, overview = movie.overview,
availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN, availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
releaseDate = movie.releaseDate, releaseDate = toLocalDate(movie.releaseDate),
posterPath = movie.posterPath, posterPath = movie.posterPath,
backdropPath = movie.backdropPath, backdropPath = movie.backdropPath,
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -120,7 +123,7 @@ data class DiscoverItem(
subtitle = null, subtitle = null,
overview = movie.overview, overview = movie.overview,
availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN, availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
releaseDate = movie.releaseDate, releaseDate = toLocalDate(movie.releaseDate),
posterPath = movie.posterPath, posterPath = movie.posterPath,
backdropPath = movie.backdropPath, backdropPath = movie.backdropPath,
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -133,7 +136,7 @@ data class DiscoverItem(
subtitle = null, subtitle = null,
overview = tv.overview, overview = tv.overview,
availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN, availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
releaseDate = tv.firstAirDate, releaseDate = toLocalDate(tv.firstAirDate),
posterPath = tv.posterPath, posterPath = tv.posterPath,
backdropPath = tv.backdropPath, backdropPath = tv.backdropPath,
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -146,7 +149,7 @@ data class DiscoverItem(
subtitle = null, subtitle = null,
overview = tv.overview, overview = tv.overview,
availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN, availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
releaseDate = tv.firstAirDate, releaseDate = toLocalDate(tv.firstAirDate),
posterPath = tv.posterPath, posterPath = tv.posterPath,
backdropPath = tv.backdropPath, backdropPath = tv.backdropPath,
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -161,7 +164,7 @@ data class DiscoverItem(
availability = availability =
SeerrAvailability.from(search.mediaInfo?.status) SeerrAvailability.from(search.mediaInfo?.status)
?: SeerrAvailability.UNKNOWN, ?: SeerrAvailability.UNKNOWN,
releaseDate = search.releaseDate ?: search.firstAirDate, releaseDate = toLocalDate(search.releaseDate ?: search.firstAirDate),
posterPath = search.posterPath, posterPath = search.posterPath,
backdropPath = search.backdropPath, backdropPath = search.backdropPath,
jellyfinItemId = search.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = search.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -176,7 +179,7 @@ data class DiscoverItem(
availability = availability =
SeerrAvailability.from(credit.mediaInfo?.status) SeerrAvailability.from(credit.mediaInfo?.status)
?: SeerrAvailability.UNKNOWN, ?: SeerrAvailability.UNKNOWN,
releaseDate = credit.firstAirDate, releaseDate = toLocalDate(credit.firstAirDate),
posterPath = credit.posterPath, posterPath = credit.posterPath,
backdropPath = credit.backdropPath, backdropPath = credit.backdropPath,
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
@ -191,7 +194,7 @@ data class DiscoverItem(
availability = availability =
SeerrAvailability.from(credit.mediaInfo?.status) SeerrAvailability.from(credit.mediaInfo?.status)
?: SeerrAvailability.UNKNOWN, ?: SeerrAvailability.UNKNOWN,
releaseDate = credit.firstAirDate, releaseDate = toLocalDate(credit.firstAirDate),
posterPath = credit.posterPath, posterPath = credit.posterPath,
backdropPath = credit.backdropPath, backdropPath = credit.backdropPath,
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(), jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),

View file

@ -4,9 +4,11 @@ import androidx.annotation.StringRes
import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.R
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.MediaSegmentType import org.jellyfin.sdk.model.api.MediaSegmentType
import timber.log.Timber
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.util.Locale import java.util.Locale
@ -23,6 +25,16 @@ fun formatDateTime(dateTime: LocalDateTime): String = DateFormatter.format(dateT
fun formatDate(dateTime: LocalDate): String = DateFormatter.format(dateTime) fun formatDate(dateTime: LocalDate): String = DateFormatter.format(dateTime)
fun toLocalDate(date: String?): LocalDate? =
date?.let {
try {
LocalDate.parse(it)
} catch (_: DateTimeParseException) {
Timber.w("Could not parse date: %s", date)
null
}
}
/** /**
* If the item has season & episode info, format as `S# E#` * If the item has season & episode info, format as `S# E#`
*/ */

View file

@ -189,7 +189,7 @@ fun DiscoverItemCard(
.enableMarquee(focusedAfterDelay), .enableMarquee(focusedAfterDelay),
) )
Text( Text(
text = item?.releaseDate ?: "", text = item?.releaseDate?.year?.toString() ?: "",
maxLines = 1, maxLines = 1,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = modifier =

View file

@ -0,0 +1,24 @@
package com.github.damontecres.wholphin.util
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.time.LocalDate
import java.time.format.DateTimeFormatter
object LocalDateSerializer : KSerializer<LocalDate> {
override val descriptor: SerialDescriptor
get() = SerialDescriptor("LocalDate", String.serializer().descriptor)
override fun serialize(
encoder: Encoder,
value: LocalDate,
) {
encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value))
}
override fun deserialize(decoder: Decoder): LocalDate =
decoder.decodeString().let { LocalDate.parse(it, DateTimeFormatter.ISO_LOCAL_DATE) }
}