mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Better support for using thumbnails
This commit is contained in:
parent
f786ec647e
commit
9a86e854e9
8 changed files with 174 additions and 56 deletions
|
|
@ -199,4 +199,7 @@ data class HomeRowViewOptions(
|
||||||
val imageType: ViewOptionImageType = ViewOptionImageType.PRIMARY,
|
val imageType: ViewOptionImageType = ViewOptionImageType.PRIMARY,
|
||||||
val showTitles: Boolean = false,
|
val showTitles: Boolean = false,
|
||||||
val useSeries: Boolean = true,
|
val useSeries: Boolean = true,
|
||||||
|
val episodeContentScale: PrefContentScale = PrefContentScale.FIT,
|
||||||
|
val episodeAspectRatio: AspectRatio = AspectRatio.TALL,
|
||||||
|
val episodeImageType: ViewOptionImageType = ViewOptionImageType.PRIMARY,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -976,8 +976,6 @@ val basicPreferences =
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
val uiPreferences = listOf<PreferenceGroup>()
|
|
||||||
|
|
||||||
private val ExoPlayerSettings =
|
private val ExoPlayerSettings =
|
||||||
listOf(
|
listOf(
|
||||||
AppPreference.FfmpegPreference,
|
AppPreference.FfmpegPreference,
|
||||||
|
|
|
||||||
|
|
@ -371,12 +371,36 @@ fun HomePageContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
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(
|
BannerCard(
|
||||||
name = item?.data?.seriesName ?: item?.name,
|
name = item?.data?.seriesName ?: item?.name,
|
||||||
item = item,
|
item = item,
|
||||||
aspectRatio = viewOptions.aspectRatio.ratio,
|
aspectRatio = ratio,
|
||||||
imageType = viewOptions.imageType.imageType,
|
imageType = imageType,
|
||||||
imageContentScale = viewOptions.contentScale.scale,
|
imageContentScale = scale,
|
||||||
cornerText = item?.ui?.episdodeUnplayedCornerText,
|
cornerText = item?.ui?.episdodeUnplayedCornerText,
|
||||||
played = item?.data?.userData?.played ?: false,
|
played = item?.data?.userData?.played ?: false,
|
||||||
favorite = item?.favorite ?: false,
|
favorite = item?.favorite ?: false,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
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.compose.ui.unit.dp
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.surfaceColorAtElevation
|
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.AspectRatio
|
||||||
import com.github.damontecres.wholphin.ui.Cards
|
import com.github.damontecres.wholphin.ui.Cards
|
||||||
import com.github.damontecres.wholphin.ui.components.ViewOptionImageType
|
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.ifElse
|
||||||
import com.github.damontecres.wholphin.ui.preferences.ComposablePreference
|
import com.github.damontecres.wholphin.ui.preferences.ComposablePreference
|
||||||
|
import com.github.damontecres.wholphin.ui.preferences.PreferenceGroup
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeRowSettings(
|
fun HomeRowSettings(
|
||||||
title: String,
|
title: String,
|
||||||
|
preferenceOptions: List<PreferenceGroup<HomeRowViewOptions>>,
|
||||||
viewOptions: HomeRowViewOptions,
|
viewOptions: HomeRowViewOptions,
|
||||||
onViewOptionsChange: (HomeRowViewOptions) -> Unit,
|
onViewOptionsChange: (HomeRowViewOptions) -> Unit,
|
||||||
onApplyApplyAll: () -> Unit,
|
onApplyApplyAll: () -> Unit,
|
||||||
userGenreSettings: Boolean,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
defaultViewOptions: HomeRowViewOptions = HomeRowViewOptions(),
|
defaultViewOptions: HomeRowViewOptions = HomeRowViewOptions(),
|
||||||
) {
|
) {
|
||||||
val options = if (userGenreSettings) Options.GENRE_OPTIONS else Options.OPTIONS
|
|
||||||
val firstFocus = remember { FocusRequester() }
|
val firstFocus = remember { FocusRequester() }
|
||||||
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
TitleText(title)
|
TitleText(title)
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
itemsIndexed(options) { index, pref ->
|
preferenceOptions.forEachIndexed { groupIndex, prefGroup ->
|
||||||
pref as AppPreference<HomeRowViewOptions, Any>
|
if (preferenceOptions.size > 1) {
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
item {
|
||||||
val value = pref.getter.invoke(viewOptions)
|
TitleText(stringResource(prefGroup.title))
|
||||||
ComposablePreference(
|
}
|
||||||
preference = pref,
|
}
|
||||||
value = value,
|
itemsIndexed(prefGroup.preferences) { index, pref ->
|
||||||
onNavigate = {},
|
pref as AppPreference<HomeRowViewOptions, Any>
|
||||||
onValueChange = { newValue ->
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
onViewOptionsChange.invoke(pref.setter(viewOptions, newValue))
|
val value = pref.getter.invoke(viewOptions)
|
||||||
},
|
ComposablePreference(
|
||||||
interactionSource = interactionSource,
|
preference = pref,
|
||||||
onClickPreference = { pref ->
|
value = value,
|
||||||
if (pref == Options.ViewOptionsReset) {
|
onNavigate = {},
|
||||||
onViewOptionsChange.invoke(defaultViewOptions)
|
onValueChange = { newValue ->
|
||||||
} else if (pref == Options.ViewOptionsApplyAll) {
|
onViewOptionsChange.invoke(pref.setter(viewOptions, newValue))
|
||||||
onApplyApplyAll.invoke()
|
},
|
||||||
}
|
interactionSource = interactionSource,
|
||||||
},
|
onClickPreference = { pref ->
|
||||||
modifier =
|
if (pref == Options.ViewOptionsReset) {
|
||||||
Modifier
|
onViewOptionsChange.invoke(defaultViewOptions)
|
||||||
.background(
|
} else if (pref == Options.ViewOptionsApplyAll) {
|
||||||
MaterialTheme.colorScheme.surfaceColorAtElevation(
|
onApplyApplyAll.invoke()
|
||||||
5.dp,
|
}
|
||||||
),
|
},
|
||||||
).ifElse(index == 0, Modifier.focusRequester(firstFocus)),
|
modifier =
|
||||||
)
|
Modifier
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||||
|
5.dp,
|
||||||
|
),
|
||||||
|
).ifElse(index == 0, Modifier.focusRequester(firstFocus)),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,33 +164,111 @@ internal object Options {
|
||||||
)
|
)
|
||||||
|
|
||||||
val ViewOptionsApplyAll =
|
val ViewOptionsApplyAll =
|
||||||
AppClickablePreference<ViewOptions>(
|
AppClickablePreference<HomeRowViewOptions>(
|
||||||
title = R.string.apply_all_rows,
|
title = R.string.apply_all_rows,
|
||||||
)
|
)
|
||||||
|
|
||||||
val ViewOptionsReset =
|
val ViewOptionsReset =
|
||||||
AppClickablePreference<ViewOptions>(
|
AppClickablePreference<HomeRowViewOptions>(
|
||||||
title = R.string.reset,
|
title = R.string.reset,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val ViewOptionsEpisodeContentScale =
|
||||||
|
AppChoicePreference<HomeRowViewOptions, PrefContentScale>(
|
||||||
|
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<HomeRowViewOptions, AspectRatio>(
|
||||||
|
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<HomeRowViewOptions, ViewOptionImageType>(
|
||||||
|
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 =
|
val OPTIONS =
|
||||||
listOf(
|
listOf(
|
||||||
ViewOptionsImageType,
|
PreferenceGroup(
|
||||||
ViewOptionsAspectRatio,
|
title = R.string.general,
|
||||||
// TODO
|
preferences =
|
||||||
|
listOf(
|
||||||
|
ViewOptionsImageType,
|
||||||
|
ViewOptionsAspectRatio,
|
||||||
|
// TODO
|
||||||
// ViewOptionsShowTitles,
|
// ViewOptionsShowTitles,
|
||||||
ViewOptionsUseSeries,
|
ViewOptionsUseSeries,
|
||||||
ViewOptionsCardHeight,
|
ViewOptionsCardHeight,
|
||||||
ViewOptionsSpacing,
|
ViewOptionsSpacing,
|
||||||
ViewOptionsContentScale,
|
ViewOptionsContentScale,
|
||||||
// ViewOptionsApplyAll,
|
// 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 =
|
val GENRE_OPTIONS =
|
||||||
listOf(
|
listOf(
|
||||||
ViewOptionsCardHeight,
|
PreferenceGroup(
|
||||||
ViewOptionsSpacing,
|
title = R.string.general,
|
||||||
ViewOptionsReset,
|
preferences =
|
||||||
|
listOf(
|
||||||
|
ViewOptionsCardHeight,
|
||||||
|
ViewOptionsSpacing,
|
||||||
|
ViewOptionsReset,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,21 @@ fun HomeSettingsPage(
|
||||||
val row =
|
val row =
|
||||||
state.rows
|
state.rows
|
||||||
.first { it.id == dest.rowId }
|
.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(
|
HomeRowSettings(
|
||||||
title = row.title,
|
title = row.title,
|
||||||
|
preferenceOptions = preferenceOptions,
|
||||||
viewOptions = row.config.viewOptions,
|
viewOptions = row.config.viewOptions,
|
||||||
onViewOptionsChange = {
|
onViewOptionsChange = {
|
||||||
viewModel.updateViewOptions(dest.rowId, it)
|
viewModel.updateViewOptions(dest.rowId, it)
|
||||||
|
|
@ -160,7 +173,6 @@ fun HomeSettingsPage(
|
||||||
onApplyApplyAll = {
|
onApplyApplyAll = {
|
||||||
viewModel.updateViewOptionsForAll(row.config.viewOptions)
|
viewModel.updateViewOptionsForAll(row.config.viewOptions)
|
||||||
},
|
},
|
||||||
userGenreSettings = row.config is HomeRowConfig.Genres,
|
|
||||||
modifier = destModifier,
|
modifier = destModifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import kotlinx.serialization.Serializable
|
||||||
/**
|
/**
|
||||||
* A group of preferences
|
* A group of preferences
|
||||||
*/
|
*/
|
||||||
data class PreferenceGroup(
|
data class PreferenceGroup<T>(
|
||||||
@param:StringRes val title: Int,
|
@param:StringRes val title: Int,
|
||||||
val preferences: List<AppPreference<AppPreferences, out Any?>>,
|
val preferences: List<AppPreference<T, out Any?>>,
|
||||||
val conditionalPreferences: List<ConditionalPreferences> = listOf(),
|
val conditionalPreferences: List<ConditionalPreferences> = listOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -34,7 +34,6 @@ sealed interface PreferenceValidation {
|
||||||
enum class PreferenceScreenOption {
|
enum class PreferenceScreenOption {
|
||||||
BASIC,
|
BASIC,
|
||||||
ADVANCED,
|
ADVANCED,
|
||||||
USER_INTERFACE,
|
|
||||||
SUBTITLES,
|
SUBTITLES,
|
||||||
EXO_PLAYER,
|
EXO_PLAYER,
|
||||||
MPV,
|
MPV,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ import com.github.damontecres.wholphin.preferences.MpvPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||||
import com.github.damontecres.wholphin.preferences.advancedPreferences
|
import com.github.damontecres.wholphin.preferences.advancedPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.basicPreferences
|
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.preferences.updatePlaybackPreferences
|
||||||
import com.github.damontecres.wholphin.services.UpdateChecker
|
import com.github.damontecres.wholphin.services.UpdateChecker
|
||||||
import com.github.damontecres.wholphin.ui.components.ConfirmDialog
|
import com.github.damontecres.wholphin.ui.components.ConfirmDialog
|
||||||
|
|
@ -125,7 +124,6 @@ fun PreferencesContent(
|
||||||
when (preferenceScreenOption) {
|
when (preferenceScreenOption) {
|
||||||
PreferenceScreenOption.BASIC -> basicPreferences
|
PreferenceScreenOption.BASIC -> basicPreferences
|
||||||
PreferenceScreenOption.ADVANCED -> advancedPreferences
|
PreferenceScreenOption.ADVANCED -> advancedPreferences
|
||||||
PreferenceScreenOption.USER_INTERFACE -> uiPreferences
|
|
||||||
PreferenceScreenOption.SUBTITLES -> SubtitleSettings.preferences
|
PreferenceScreenOption.SUBTITLES -> SubtitleSettings.preferences
|
||||||
PreferenceScreenOption.EXO_PLAYER -> ExoPlayerPreferences
|
PreferenceScreenOption.EXO_PLAYER -> ExoPlayerPreferences
|
||||||
PreferenceScreenOption.MPV -> MpvPreferences
|
PreferenceScreenOption.MPV -> MpvPreferences
|
||||||
|
|
@ -134,7 +132,6 @@ fun PreferencesContent(
|
||||||
when (preferenceScreenOption) {
|
when (preferenceScreenOption) {
|
||||||
PreferenceScreenOption.BASIC -> R.string.settings
|
PreferenceScreenOption.BASIC -> R.string.settings
|
||||||
PreferenceScreenOption.ADVANCED -> R.string.advanced_settings
|
PreferenceScreenOption.ADVANCED -> R.string.advanced_settings
|
||||||
PreferenceScreenOption.USER_INTERFACE -> R.string.ui_interface
|
|
||||||
PreferenceScreenOption.SUBTITLES -> R.string.subtitle_style
|
PreferenceScreenOption.SUBTITLES -> R.string.subtitle_style
|
||||||
PreferenceScreenOption.EXO_PLAYER -> R.string.exoplayer_options
|
PreferenceScreenOption.EXO_PLAYER -> R.string.exoplayer_options
|
||||||
PreferenceScreenOption.MPV -> R.string.mpv_options
|
PreferenceScreenOption.MPV -> R.string.mpv_options
|
||||||
|
|
@ -526,7 +523,6 @@ fun PreferencesPage(
|
||||||
when (preferenceScreenOption) {
|
when (preferenceScreenOption) {
|
||||||
PreferenceScreenOption.BASIC,
|
PreferenceScreenOption.BASIC,
|
||||||
PreferenceScreenOption.ADVANCED,
|
PreferenceScreenOption.ADVANCED,
|
||||||
PreferenceScreenOption.USER_INTERFACE,
|
|
||||||
PreferenceScreenOption.EXO_PLAYER,
|
PreferenceScreenOption.EXO_PLAYER,
|
||||||
PreferenceScreenOption.MPV,
|
PreferenceScreenOption.MPV,
|
||||||
-> {
|
-> {
|
||||||
|
|
|
||||||
|
|
@ -476,6 +476,7 @@
|
||||||
<string name="add_row_for">Add row for %1$s</string>
|
<string name="add_row_for">Add row for %1$s</string>
|
||||||
<string name="overwrite_server_settings">Overwrite settings on server?</string>
|
<string name="overwrite_server_settings">Overwrite settings on server?</string>
|
||||||
<string name="overwrite_local_settings">Overwrite local settings?</string>
|
<string name="overwrite_local_settings">Overwrite local settings?</string>
|
||||||
|
<string name="for_episodes">For episodes</string>
|
||||||
|
|
||||||
<string-array name="theme_song_volume">
|
<string-array name="theme_song_volume">
|
||||||
<item>Disabled</item>
|
<item>Disabled</item>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue