Show extras for Movies & TV Shows (#224)

## Description
Shows local extras (clips, interviews, etc) for movies and tv shows

Extras are grouped by type and clicking on the type will go to a grid
page listing all of the items. However, if there is just one of that
type, it is shown in-line.

Trailers still have on their own row. And theme songs & theme videos are
not shown.

## Issues
Closes #123
This commit is contained in:
damontecres 2025-11-15 13:25:44 -05:00 committed by GitHub
parent 2f56a3a114
commit 93d82a263d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 542 additions and 36 deletions

View file

@ -0,0 +1,78 @@
package com.github.damontecres.wholphin.data
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.data.model.BaseItem
import com.github.damontecres.wholphin.ui.nav.Destination
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.ExtraType
sealed interface ExtrasItem {
val parentId: UUID
val type: ExtraType
val destination: Destination
val title: String?
val imageUrl: String?
data class Group(
override val parentId: UUID,
override val type: ExtraType,
val items: List<BaseItem>,
) : ExtrasItem {
override val destination: Destination =
Destination.ItemGrid(null, type.stringRes, items.map { it.id })
override val title: String? = null
override val imageUrl: String? = items.random().imageUrl
}
data class Single(
override val parentId: UUID,
override val type: ExtraType,
val item: BaseItem,
) : ExtrasItem {
override val destination: Destination =
Destination.Playback(
item = item,
)
override val title: String? get() = item.title
override val imageUrl: String? get() = item.imageUrl
}
}
@get:StringRes
val ExtraType.stringRes: Int
get() =
when (this) {
ExtraType.UNKNOWN -> R.string.other_extras
ExtraType.CLIP -> R.string.clips
ExtraType.TRAILER -> R.string.trailers
ExtraType.BEHIND_THE_SCENES -> R.string.behind_the_scenes
ExtraType.DELETED_SCENE -> R.string.deleted_scenes
ExtraType.INTERVIEW -> R.string.interviews
ExtraType.SCENE -> R.string.scenes
ExtraType.SAMPLE -> R.string.samples
ExtraType.THEME_SONG -> R.string.theme_songs
ExtraType.THEME_VIDEO -> R.string.theme_videos
ExtraType.FEATURETTE -> R.string.featurettes
ExtraType.SHORT -> R.string.shorts
}
@get:PluralsRes
val ExtraType.pluralRes: Int
get() =
when (this) {
ExtraType.UNKNOWN -> R.plurals.other_extras
ExtraType.CLIP -> R.plurals.clips
ExtraType.TRAILER -> R.plurals.trailers
ExtraType.BEHIND_THE_SCENES -> R.plurals.behind_the_scenes
ExtraType.DELETED_SCENE -> R.plurals.deleted_scenes
ExtraType.INTERVIEW -> R.plurals.interviews
ExtraType.SCENE -> R.plurals.scenes
ExtraType.SAMPLE -> R.plurals.samples
ExtraType.THEME_SONG -> R.plurals.theme_songs
ExtraType.THEME_VIDEO -> R.plurals.theme_videos
ExtraType.FEATURETTE -> R.plurals.featurettes
ExtraType.SHORT -> R.plurals.shorts
}