Add preset for home page episode thumbnails (#954)

## Description
Adds a preset for "Episode thumbnails" which shows episodes using their
Primary image (ie a thumbnail or screenshot of the episode).

The previous "Thumbnails" preset is renamed "Series Thumbs" because it
uses the episode's Series Thumb image.

Also fixes a bug where toggling "Use series" might not update the home
page preview automatically.

### Related issues
Fixes #940

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-02-23 09:56:22 -05:00 committed by GitHub
parent a51d9e9c65
commit a44fad890f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 66 additions and 15 deletions

View file

@ -68,6 +68,7 @@ fun BannerCard(
interactionSource: MutableInteractionSource? = null,
imageType: ImageType = ImageType.PRIMARY,
imageContentScale: ContentScale = ContentScale.FillBounds,
useSeriesForPrimary: Boolean = true,
) {
val imageUrlService = LocalImageUrlService.current
val density = LocalDensity.current
@ -82,7 +83,7 @@ fun BannerCard(
}
}
val imageUrl =
remember(item, fillHeight, imageType) {
remember(item, fillHeight, imageType, useSeriesForPrimary) {
if (item != null) {
item.imageUrlOverride
?: imageUrlService.getItemImageUrl(
@ -90,6 +91,7 @@ fun BannerCard(
imageType,
fillWidth = null,
fillHeight = fillHeight,
useSeriesForPrimary = useSeriesForPrimary,
)
} else {
null
@ -208,6 +210,7 @@ fun BannerCardWithTitle(
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
imageType: ImageType = ImageType.PRIMARY,
imageContentScale: ContentScale = ContentScale.FillBounds,
useSeriesForPrimary: Boolean = item?.useSeriesForPrimary ?: true,
) {
val focused by interactionSource.collectIsFocusedAsState()
val spaceBetween by animateDpAsState(if (focused) 12.dp else 4.dp)
@ -234,6 +237,7 @@ fun BannerCardWithTitle(
interactionSource = interactionSource,
imageType = imageType,
imageContentScale = imageContentScale,
useSeriesForPrimary = useSeriesForPrimary,
)
Column(
verticalArrangement = Arrangement.spacedBy(0.dp),

View file

@ -524,6 +524,7 @@ fun HomePageCardContent(
onLongClick = onLongClick,
modifier = modifier,
cardHeight = viewOptions.heightDp.dp,
useSeriesForPrimary = viewOptions.useSeries,
)
} else {
BannerCard(
@ -543,6 +544,7 @@ fun HomePageCardContent(
modifier = modifier,
interactionSource = null,
cardHeight = viewOptions.heightDp.dp,
useSeriesForPrimary = viewOptions.useSeries,
)
}
}

View file

@ -123,7 +123,7 @@ data class HomeRowPresets(
)
}
val Thumbnails by lazy {
val SeriesThumbs by lazy {
val height = 148
val epHeight = 100
HomeRowPresets(
@ -132,6 +132,7 @@ data class HomeRowPresets(
heightDp = epHeight,
imageType = ViewOptionImageType.THUMB,
aspectRatio = AspectRatio.WIDE,
useSeries = true,
episodeImageType = ViewOptionImageType.THUMB,
episodeAspectRatio = AspectRatio.WIDE,
),
@ -164,6 +165,50 @@ data class HomeRowPresets(
genreSize = epHeight,
)
}
val EpisodeThumbnails by lazy {
val height = 148
val epHeight = 100
HomeRowPresets(
continueWatching =
HomeRowViewOptions(
heightDp = epHeight,
imageType = ViewOptionImageType.THUMB,
aspectRatio = AspectRatio.WIDE,
showTitles = true,
useSeries = false,
episodeImageType = ViewOptionImageType.PRIMARY,
episodeAspectRatio = AspectRatio.WIDE,
),
movieLibrary =
HomeRowViewOptions(
heightDp = height,
),
tvLibrary =
HomeRowViewOptions(
heightDp = height,
),
videoLibrary =
HomeRowViewOptions(
heightDp = epHeight,
aspectRatio = AspectRatio.WIDE,
),
photoLibrary =
HomeRowViewOptions(
heightDp = epHeight,
aspectRatio = AspectRatio.WIDE,
contentScale = PrefContentScale.CROP,
),
playlist =
HomeRowViewOptions(
heightDp = epHeight,
aspectRatio = AspectRatio.SQUARE,
contentScale = PrefContentScale.FIT,
),
liveTv = HomeRowViewOptions.liveTvDefault,
genreSize = epHeight,
)
}
}
}
@ -173,13 +218,13 @@ fun HomeRowPresetsContent(
modifier: Modifier = Modifier,
) {
val presets =
remember {
listOf(
"Wholphin Default",
"Wholphin Compact",
"Thumbnails",
stringResource(R.string.display_preset_default) to HomeRowPresets.WholphinDefault,
stringResource(R.string.display_preset_compact) to HomeRowPresets.WholphinCompact,
stringResource(R.string.display_preset_series_thumb) to HomeRowPresets.SeriesThumbs,
stringResource(R.string.display_preset_episode_thumbnails) to HomeRowPresets.EpisodeThumbnails,
)
}
val focusRequesters = remember { List(presets.size) { FocusRequester() } }
LaunchedEffect(Unit) { focusRequesters[0].tryRequestFocus() }
Column(modifier = modifier) {
@ -192,16 +237,12 @@ fun HomeRowPresetsContent(
.fillMaxHeight()
.focusRestorer(focusRequesters[0]),
) {
itemsIndexed(presets) { index, title ->
itemsIndexed(presets) { index, (title, preset) ->
HomeSettingsListItem(
selected = false,
headlineText = title,
onClick = {
when (index) {
0 -> onApply.invoke(HomeRowPresets.WholphinDefault)
1 -> onApply.invoke(HomeRowPresets.WholphinCompact)
2 -> onApply.invoke(HomeRowPresets.Thumbnails)
}
onApply.invoke(preset)
},
modifier = Modifier.focusRequester(focusRequesters[index]),
)

View file

@ -522,6 +522,10 @@
<string name="display_presets">Display presets</string>
<string name="display_presets_description">Built-in presets to quickly style all rows</string>
<string name="customize_home_summary">Choose rows and images on the home page</string>
<string name="display_preset_default">Wholphin Default</string>
<string name="display_preset_compact">Wholphin Compact</string>
<string name="display_preset_series_thumb">Series Thumb images</string>
<string name="display_preset_episode_thumbnails">Episode Thumbnail images</string>
<string-array name="theme_song_volume">
<item>Disabled</item>