Restore per-row Card size and Spacing as multipliers; drop legacy spacing field

Per-row card size and spacing return to HomeRowSettings, reframed as
percent multipliers that compound with the global Display Size sliders
instead of the old absolute heightDp / spacing values. Display Presets
continue to set absolute heightDp for special cases (Favorite Episode,
Compact, etc.); the multiplier applies on top of whatever base is in
effect for that row.

HomeRowViewOptions:
- Drops the unused absolute `spacing: Int = 16` field.
- Adds `cardSizeMultiplier: Int = 100` and `spacingMultiplier: Int = 100`.
- `heightDp` stays as the per-row absolute set by Display Presets.

resolvedCardHeight() in InterfaceHelpers now layers the multiplier on
top of the existing per-row vs global resolution.

HomeRowSettings exposes Card size and Spacing sliders for each row
(range 50-150, step 5, default 100) under "General". Genre rows keep
their stripped-down options list and skip both. On HomePage, the
per-row spacingMultiplier compounds with the global Spacing slider for
that row's inter-card gap.
This commit is contained in:
Justin Visser 2026-05-26 11:56:57 +02:00
parent 3060887756
commit 1f9188abc0
4 changed files with 32 additions and 24 deletions

View file

@ -217,14 +217,17 @@ data class HomePageSettings(
const val SUPPORTED_HOME_PAGE_SETTINGS_VERSION = 1
/**
* View options for displaying a row
* View options for displaying a row.
*
* Allows for changing things like height or aspect ratio
* [heightDp] of `0` means "use the global card size"; a non-zero value is treated as a per-row
* absolute override (set by Display Presets). [cardSizeMultiplier] and [spacingMultiplier] are
* percents (default 100) applied on top of the global Card size / Spacing sliders for this row.
*/
@Serializable
data class HomeRowViewOptions(
val heightDp: Int = 0,
val spacing: Int = 16,
val cardSizeMultiplier: Int = 100,
val spacingMultiplier: Int = 100,
val contentScale: PrefContentScale = PrefContentScale.FILL,
val aspectRatio: AspectRatio = AspectRatio.TALL,
val imageType: ViewOptionImageType = ViewOptionImageType.PRIMARY,

View file

@ -430,7 +430,11 @@ fun HomePageContent(
.focusRequester(rowFocusRequesters[rowIndex])
.animateItem(),
horizontalPadding = BASE_SPACING_DP.dp,
cardSpacing = LocalInterfaceCustomization.current.spacingDp.dp,
cardSpacing =
(
LocalInterfaceCustomization.current.spacingDp * viewOptions.spacingMultiplier /
100
).dp,
cardContent = { index, item, cardModifier, onClick, onLongClick ->
val onFocus =
remember(rowIndex, index) {

View file

@ -102,7 +102,6 @@ fun HomeRowSettings(
onViewOptionsChange.invoke(
viewOptions.copy(
heightDp = Cards.HEIGHT_EPISODE,
spacing = 20,
imageType = ViewOptionImageType.THUMB,
aspectRatio = AspectRatio.WIDE,
contentScale = PrefContentScale.FIT,
@ -257,25 +256,28 @@ fun ByParentSortDialogContent(
}
internal object Options {
val ViewOptionsCardHeight =
val ViewOptionsCardSize =
AppSliderPreference<HomeRowViewOptions>(
title = R.string.height,
defaultValue = Cards.HEIGHT_2X3_DP.toLong(),
min = 64L,
max = Cards.HEIGHT_2X3_DP + 64L,
interval = 4,
getter = { it.heightDp.toLong() },
setter = { prefs, value -> prefs.copy(heightDp = value.toInt()) },
title = R.string.card_size,
defaultValue = 100,
min = 50,
max = 150,
interval = 5,
getter = { it.cardSizeMultiplier.toLong() },
setter = { vo, value -> vo.copy(cardSizeMultiplier = value.toInt()) },
summarizer = { it?.let { "$it%" } },
)
val ViewOptionsSpacing =
AppSliderPreference<HomeRowViewOptions>(
title = R.string.spacing,
defaultValue = 16,
min = 0,
max = 32,
interval = 2,
getter = { it.spacing.toLong() },
setter = { prefs, value -> prefs.copy(spacing = value.toInt()) },
defaultValue = 100,
min = 50,
max = 150,
interval = 5,
getter = { it.spacingMultiplier.toLong() },
setter = { vo, value -> vo.copy(spacingMultiplier = value.toInt()) },
summarizer = { it?.let { "$it%" } },
)
val ViewOptionsContentScale =
@ -395,7 +397,7 @@ internal object Options {
title = R.string.general,
preferences =
listOf(
ViewOptionsCardHeight,
ViewOptionsCardSize,
ViewOptionsSpacing,
ViewOptionsShowTitles,
ViewOptionsImageType,
@ -421,7 +423,7 @@ internal object Options {
title = R.string.general,
preferences =
listOf(
ViewOptionsCardHeight,
ViewOptionsCardSize,
ViewOptionsSpacing,
ViewOptionsShowTitles,
ViewOptionsImageType,
@ -455,8 +457,6 @@ internal object Options {
title = R.string.general,
preferences =
listOf(
ViewOptionsCardHeight,
ViewOptionsSpacing,
ViewOptionsReset,
),
),

View file

@ -11,7 +11,8 @@ import com.github.damontecres.wholphin.ui.Cards
internal fun HomeRowViewOptions.resolvedCardHeight(): Dp {
val global = LocalInterfaceCustomization.current.cardHeightDp
val isOverride = heightDp > 0 && heightDp != Cards.HEIGHT_2X3_DP
return (if (isOverride) heightDp else global).dp
val base = if (isOverride) heightDp else global
return (base * cardSizeMultiplier / 100).dp
}
internal fun Int.withinBoundsOrDefault(preference: AppSliderPreference<*>): Int {