From 9a86e854e9ca5a719439bc3ca7312dc45a41d572 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Sun, 1 Feb 2026 17:33:46 -0500 Subject: [PATCH] Better support for using thumbnails --- .../wholphin/data/model/HomeRowConfig.kt | 3 + .../wholphin/preferences/AppPreference.kt | 2 - .../damontecres/wholphin/ui/main/HomePage.kt | 30 ++- .../ui/main/settings/HomeRowSettings.kt | 171 +++++++++++++----- .../ui/main/settings/HomeSettingsPage.kt | 14 +- .../ui/preferences/PreferenceUtils.kt | 5 +- .../ui/preferences/PreferencesContent.kt | 4 - app/src/main/res/values/strings.xml | 1 + 8 files changed, 174 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt b/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt index 36c28388..03c662b7 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt @@ -199,4 +199,7 @@ data class HomeRowViewOptions( val imageType: ViewOptionImageType = ViewOptionImageType.PRIMARY, val showTitles: Boolean = false, val useSeries: Boolean = true, + val episodeContentScale: PrefContentScale = PrefContentScale.FIT, + val episodeAspectRatio: AspectRatio = AspectRatio.TALL, + val episodeImageType: ViewOptionImageType = ViewOptionImageType.PRIMARY, ) diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt index cc561411..28903af3 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt @@ -976,8 +976,6 @@ val basicPreferences = ), ) -val uiPreferences = listOf() - private val ExoPlayerSettings = listOf( AppPreference.FfmpegPreference, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt index db7f8eb8..d3d1a639 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt @@ -371,12 +371,36 @@ fun HomePageContent( } else -> { + val imageType = + remember(item, viewOptions) { + if (item?.type == BaseItemKind.EPISODE) { + viewOptions.episodeImageType.imageType + } else { + viewOptions.imageType.imageType + } + } + val ratio = + remember(item, viewOptions) { + if (item?.type == BaseItemKind.EPISODE) { + viewOptions.episodeAspectRatio.ratio + } else { + viewOptions.aspectRatio.ratio + } + } + val scale = + remember(item, viewOptions) { + if (item?.type == BaseItemKind.EPISODE) { + viewOptions.episodeContentScale.scale + } else { + viewOptions.contentScale.scale + } + } BannerCard( name = item?.data?.seriesName ?: item?.name, item = item, - aspectRatio = viewOptions.aspectRatio.ratio, - imageType = viewOptions.imageType.imageType, - imageContentScale = viewOptions.contentScale.scale, + aspectRatio = ratio, + imageType = imageType, + imageContentScale = scale, cornerText = item?.ui?.episdodeUnplayedCornerText, played = item?.data?.userData?.played ?: false, favorite = item?.favorite ?: false, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeRowSettings.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeRowSettings.kt index adcb3124..68f65d1a 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeRowSettings.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeRowSettings.kt @@ -11,6 +11,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.tv.material3.MaterialTheme import androidx.tv.material3.surfaceColorAtElevation @@ -25,54 +26,60 @@ import com.github.damontecres.wholphin.preferences.PrefContentScale import com.github.damontecres.wholphin.ui.AspectRatio import com.github.damontecres.wholphin.ui.Cards import com.github.damontecres.wholphin.ui.components.ViewOptionImageType -import com.github.damontecres.wholphin.ui.components.ViewOptions import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.preferences.ComposablePreference +import com.github.damontecres.wholphin.ui.preferences.PreferenceGroup import com.github.damontecres.wholphin.ui.tryRequestFocus @Composable fun HomeRowSettings( title: String, + preferenceOptions: List>, viewOptions: HomeRowViewOptions, onViewOptionsChange: (HomeRowViewOptions) -> Unit, onApplyApplyAll: () -> Unit, - userGenreSettings: Boolean, modifier: Modifier = Modifier, defaultViewOptions: HomeRowViewOptions = HomeRowViewOptions(), ) { - val options = if (userGenreSettings) Options.GENRE_OPTIONS else Options.OPTIONS val firstFocus = remember { FocusRequester() } LaunchedEffect(Unit) { firstFocus.tryRequestFocus() } Column(modifier = modifier) { TitleText(title) LazyColumn { - itemsIndexed(options) { index, pref -> - pref as AppPreference - val interactionSource = remember { MutableInteractionSource() } - val value = pref.getter.invoke(viewOptions) - ComposablePreference( - preference = pref, - value = value, - onNavigate = {}, - onValueChange = { newValue -> - onViewOptionsChange.invoke(pref.setter(viewOptions, newValue)) - }, - interactionSource = interactionSource, - onClickPreference = { pref -> - if (pref == Options.ViewOptionsReset) { - onViewOptionsChange.invoke(defaultViewOptions) - } else if (pref == Options.ViewOptionsApplyAll) { - onApplyApplyAll.invoke() - } - }, - modifier = - Modifier - .background( - MaterialTheme.colorScheme.surfaceColorAtElevation( - 5.dp, - ), - ).ifElse(index == 0, Modifier.focusRequester(firstFocus)), - ) + preferenceOptions.forEachIndexed { groupIndex, prefGroup -> + if (preferenceOptions.size > 1) { + item { + TitleText(stringResource(prefGroup.title)) + } + } + itemsIndexed(prefGroup.preferences) { index, pref -> + pref as AppPreference + val interactionSource = remember { MutableInteractionSource() } + val value = pref.getter.invoke(viewOptions) + ComposablePreference( + preference = pref, + value = value, + onNavigate = {}, + onValueChange = { newValue -> + onViewOptionsChange.invoke(pref.setter(viewOptions, newValue)) + }, + interactionSource = interactionSource, + onClickPreference = { pref -> + if (pref == Options.ViewOptionsReset) { + onViewOptionsChange.invoke(defaultViewOptions) + } else if (pref == Options.ViewOptionsApplyAll) { + onApplyApplyAll.invoke() + } + }, + modifier = + Modifier + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation( + 5.dp, + ), + ).ifElse(index == 0, Modifier.focusRequester(firstFocus)), + ) + } } } } @@ -157,33 +164,111 @@ internal object Options { ) val ViewOptionsApplyAll = - AppClickablePreference( + AppClickablePreference( title = R.string.apply_all_rows, ) val ViewOptionsReset = - AppClickablePreference( + AppClickablePreference( title = R.string.reset, ) + val ViewOptionsEpisodeContentScale = + AppChoicePreference( + title = R.string.global_content_scale, + defaultValue = PrefContentScale.FIT, + displayValues = R.array.content_scale, + getter = { it.contentScale }, + setter = { viewOptions, value -> viewOptions.copy(episodeContentScale = value) }, + indexToValue = { PrefContentScale.forNumber(it) }, + valueToIndex = { it.number }, + ) + + val ViewOptionsEpisodeAspectRatio = + AppChoicePreference( + title = R.string.aspect_ratio, + defaultValue = AspectRatio.TALL, + displayValues = R.array.aspect_ratios, + getter = { it.aspectRatio }, + setter = { viewOptions, value -> viewOptions.copy(episodeAspectRatio = value) }, + indexToValue = { AspectRatio.entries[it] }, + valueToIndex = { it.ordinal }, + ) + + val ViewOptionsEpisodeImageType = + AppChoicePreference( + title = R.string.image_type, + defaultValue = ViewOptionImageType.PRIMARY, + displayValues = R.array.image_types, + getter = { it.imageType }, + setter = { viewOptions, value -> + val aspectRatio = + when (value) { + ViewOptionImageType.PRIMARY -> AspectRatio.TALL + ViewOptionImageType.THUMB -> AspectRatio.WIDE + } + viewOptions.copy(episodeImageType = value, episodeAspectRatio = aspectRatio) + }, + indexToValue = { ViewOptionImageType.entries[it] }, + valueToIndex = { it.ordinal }, + ) + val OPTIONS = listOf( - ViewOptionsImageType, - ViewOptionsAspectRatio, - // TODO + PreferenceGroup( + title = R.string.general, + preferences = + listOf( + ViewOptionsImageType, + ViewOptionsAspectRatio, + // TODO // ViewOptionsShowTitles, - ViewOptionsUseSeries, - ViewOptionsCardHeight, - ViewOptionsSpacing, - ViewOptionsContentScale, + ViewOptionsUseSeries, + ViewOptionsCardHeight, + ViewOptionsSpacing, + ViewOptionsContentScale, // ViewOptionsApplyAll, - ViewOptionsReset, + ViewOptionsReset, + ), + ), + ) + + val OPTIONS_EPISODES = + listOf( + PreferenceGroup( + title = R.string.general, + preferences = + listOf( + ViewOptionsCardHeight, + ViewOptionsSpacing, + ViewOptionsImageType, + ViewOptionsAspectRatio, + ViewOptionsUseSeries, + ViewOptionsContentScale, + ViewOptionsReset, + ), + ), + PreferenceGroup( + title = R.string.for_episodes, + preferences = + listOf( + ViewOptionsEpisodeImageType, + ViewOptionsEpisodeContentScale, + ViewOptionsEpisodeAspectRatio, + ), + ), ) val GENRE_OPTIONS = listOf( - ViewOptionsCardHeight, - ViewOptionsSpacing, - ViewOptionsReset, + PreferenceGroup( + title = R.string.general, + preferences = + listOf( + ViewOptionsCardHeight, + ViewOptionsSpacing, + ViewOptionsReset, + ), + ), ) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt index 9b5b6c81..b34cb4a8 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt @@ -151,8 +151,21 @@ fun HomeSettingsPage( val row = state.rows .first { it.id == dest.rowId } + val preferenceOptions = + remember(row.config) { + when (row.config) { + is HomeRowConfig.ContinueWatching, + is HomeRowConfig.ContinueWatchingCombined, + -> Options.OPTIONS_EPISODES + + is HomeRowConfig.Genres -> Options.GENRE_OPTIONS + + else -> Options.OPTIONS + } + } HomeRowSettings( title = row.title, + preferenceOptions = preferenceOptions, viewOptions = row.config.viewOptions, onViewOptionsChange = { viewModel.updateViewOptions(dest.rowId, it) @@ -160,7 +173,6 @@ fun HomeSettingsPage( onApplyApplyAll = { viewModel.updateViewOptionsForAll(row.config.viewOptions) }, - userGenreSettings = row.config is HomeRowConfig.Genres, modifier = destModifier, ) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferenceUtils.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferenceUtils.kt index f84d3b89..091dd475 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferenceUtils.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferenceUtils.kt @@ -8,9 +8,9 @@ import kotlinx.serialization.Serializable /** * A group of preferences */ -data class PreferenceGroup( +data class PreferenceGroup( @param:StringRes val title: Int, - val preferences: List>, + val preferences: List>, val conditionalPreferences: List = listOf(), ) @@ -34,7 +34,6 @@ sealed interface PreferenceValidation { enum class PreferenceScreenOption { BASIC, ADVANCED, - USER_INTERFACE, SUBTITLES, EXO_PLAYER, MPV, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt index 8fedf3b6..63c5a9b1 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt @@ -50,7 +50,6 @@ import com.github.damontecres.wholphin.preferences.MpvPreferences import com.github.damontecres.wholphin.preferences.PlayerBackend import com.github.damontecres.wholphin.preferences.advancedPreferences import com.github.damontecres.wholphin.preferences.basicPreferences -import com.github.damontecres.wholphin.preferences.uiPreferences import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences import com.github.damontecres.wholphin.services.UpdateChecker import com.github.damontecres.wholphin.ui.components.ConfirmDialog @@ -125,7 +124,6 @@ fun PreferencesContent( when (preferenceScreenOption) { PreferenceScreenOption.BASIC -> basicPreferences PreferenceScreenOption.ADVANCED -> advancedPreferences - PreferenceScreenOption.USER_INTERFACE -> uiPreferences PreferenceScreenOption.SUBTITLES -> SubtitleSettings.preferences PreferenceScreenOption.EXO_PLAYER -> ExoPlayerPreferences PreferenceScreenOption.MPV -> MpvPreferences @@ -134,7 +132,6 @@ fun PreferencesContent( when (preferenceScreenOption) { PreferenceScreenOption.BASIC -> R.string.settings PreferenceScreenOption.ADVANCED -> R.string.advanced_settings - PreferenceScreenOption.USER_INTERFACE -> R.string.ui_interface PreferenceScreenOption.SUBTITLES -> R.string.subtitle_style PreferenceScreenOption.EXO_PLAYER -> R.string.exoplayer_options PreferenceScreenOption.MPV -> R.string.mpv_options @@ -526,7 +523,6 @@ fun PreferencesPage( when (preferenceScreenOption) { PreferenceScreenOption.BASIC, PreferenceScreenOption.ADVANCED, - PreferenceScreenOption.USER_INTERFACE, PreferenceScreenOption.EXO_PLAYER, PreferenceScreenOption.MPV, -> { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8b80a127..e2b050c8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -476,6 +476,7 @@ Add row for %1$s Overwrite settings on server? Overwrite local settings? + For episodes Disabled