Better home page header for Seasons (#2016)

## Description
Updates the home page header & card text when a Season type is shown,
such as in recently added for a TV Show library.

The title or logo for the series is shown with the season name as the
title. The "quick details" has the year of the season. The card shows
the unplayed count of episodes.

### Related issues
Closes #1958

### Testing
Emulator over a few days to see different seasons

## Screenshots
<img width="313" height="153" alt="image"
src="https://github.com/user-attachments/assets/c41e9edd-9f2a-4f62-b76d-e452e83dd8bf"
/>

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-09-30 17:35:29 -04:00 • committed by GitHub
parent cf74736579
commit b0d270380d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 108 additions and 38 deletions

View file

@ -112,21 +112,31 @@ data class BaseItem(
val ui =
BaseItemUi(
episodeCornerText =
data.indexNumber?.let { formatEpisodeNumber(it) }
?: data.premiereDate?.let(::formatDateTime),
episodeUnplayedCornerText =
if (type == BaseItemKind.SERIES ||
type == BaseItemKind.SEASON ||
type == BaseItemKind.EPISODE ||
type == BaseItemKind.BOX_SET
) {
if (type == BaseItemKind.EPISODE) {
data.indexNumber?.let { formatEpisodeNumber(it) }
?: data.userData
?: data.premiereDate?.let(::formatDateTime)
} else {
null
},
episodeUnplayedCornerText =
when (type) {
BaseItemKind.EPISODE -> {
data.indexNumber?.let { formatEpisodeNumber(it) }
}
BaseItemKind.SERIES,
BaseItemKind.SEASON,
BaseItemKind.BOX_SET,
-> {
data.userData
?.unplayedItemCount
?.takeIf { it > 0 }
?.let { abbreviateNumber(it) }
} else {
null
}
else -> {
null
}
},
quickDetails =
QuickDetailsData(
@ -134,33 +144,64 @@ data class BaseItem(
buildAnnotatedString {
val details =
buildList {
if (type == BaseItemKind.EPISODE) {
data.seasonEpisode?.let(::add)
data.premiereDate?.let { add(getDateFormatter().format(it)) }
} else if (type == BaseItemKind.SERIES) {
data.seriesProductionYears?.let(::add)
} else if (type == BaseItemKind.PHOTO) {
if (data.productionYear != null) {
add(data.productionYear!!.toString())
} else if (data.premiereDate != null) {
add(data.premiereDate!!.toLocalDate().toString())
}
} else if (type == BaseItemKind.BOX_SET) {
data.productionYear?.let { add(it.toString()) }
data.childCount?.let { add("$it items") }
} else if (type == BaseItemKind.PROGRAM) {
data.channelName?.let(::add)
if (data.isSeries == true) {
// TV episode
when (type) {
BaseItemKind.EPISODE -> {
data.seasonEpisode?.let(::add)
data.premiereDate?.let {
add(getDateFormatter().format(it))
add(
getDateFormatter().format(
it,
),
)
}
}
BaseItemKind.SEASON -> {
data.childCount?.let { childCount ->
add(
WholphinApplication.instance.resources.getQuantityString(
R.plurals.episodes_count,
childCount,
childCount,
),
)
}
} else {
data.productionYear?.let { add(it.toString()) }
}
} else {
data.productionYear?.let { add(it.toString()) }
BaseItemKind.SERIES -> {
data.seriesProductionYears?.let(::add)
}
BaseItemKind.PHOTO -> {
if (data.productionYear != null) {
add(data.productionYear!!.toString())
} else if (data.premiereDate != null) {
add(data.premiereDate!!.toLocalDate().toString())
}
}
BaseItemKind.BOX_SET -> {
data.productionYear?.let { add(it.toString()) }
data.childCount?.let { add("$it items") }
}
BaseItemKind.PROGRAM -> {
data.channelName?.let(::add)
if (data.isSeries == true) {
// TV episode
data.seasonEpisode?.let(::add)
data.premiereDate?.let {
add(getDateFormatter().format(it))
}
} else {
data.productionYear?.let { add(it.toString()) }
}
}
else -> {
data.productionYear?.let { add(it.toString()) }
}
}
data.runTimeTicks
?.ticks