From 5cdda5791345fa7de995602e3a41ba502ded9777 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Sun, 10 May 2026 13:47:36 +0530 Subject: [PATCH] feat; option to hide catalog underline --- .../composeResources/values/strings.xml | 2 ++ .../home/HomeCatalogSettingsRepository.kt | 23 +++++++++++++++++++ .../home/HomeCatalogSettingsSyncService.kt | 1 + .../home/components/HomeCatalogSection.kt | 9 ++++++++ .../components/HomeCollectionRowSection.kt | 10 ++++++++ .../settings/HomescreenSettingsPage.kt | 11 +++++++++ .../settings/SettingsFullScreenPages.kt | 1 + .../app/features/settings/SettingsScreen.kt | 6 +++++ .../app/features/settings/SettingsSearch.kt | 1 + 9 files changed, 64 insertions(+) diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index cd8a97e2..782a24e0 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -506,6 +506,8 @@ Display hero carousel at top of home. Hide Unreleased Content Hide movies and shows that haven't been released yet. + Hide Catalog Underline + Remove the accent line under catalog and collection titles throughout the app. %1$d of %2$d catalogs visible • %3$d hero sources selected Open a catalog only when you need to rename or reorder it. Visible diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt index e920de04..202af87a 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt @@ -33,6 +33,7 @@ data class HomeCatalogSettingsItem( data class HomeCatalogSettingsUiState( val heroEnabled: Boolean = true, val hideUnreleasedContent: Boolean = false, + val hideCatalogUnderline: Boolean = false, val items: List = emptyList(), ) { val signature: String @@ -41,6 +42,8 @@ data class HomeCatalogSettingsUiState( append('|') append(hideUnreleasedContent) append('|') + append(hideCatalogUnderline) + append('|') append( items.joinToString(separator = "|") { item -> "${item.key}:${item.order}:${item.enabled}:${item.heroSourceEnabled}:${item.customTitle}" @@ -59,6 +62,7 @@ internal data class HomeCatalogPreference( internal data class HomeCatalogSettingsSnapshot( val heroEnabled: Boolean, val hideUnreleasedContent: Boolean, + val hideCatalogUnderline: Boolean, val preferences: Map, ) @@ -75,6 +79,7 @@ private data class StoredHomeCatalogPreference( private data class StoredHomeCatalogSettingsPayload( val heroEnabled: Boolean = true, val hideUnreleasedContent: Boolean = false, + val hideCatalogUnderline: Boolean = false, val items: List = emptyList(), ) @@ -95,12 +100,14 @@ object HomeCatalogSettingsRepository { private var preferences: MutableMap = mutableMapOf() private var heroEnabled = true private var hideUnreleasedContent = false + private var hideCatalogUnderline = false fun onProfileChanged() { hasLoaded = false preferences.clear() heroEnabled = true hideUnreleasedContent = false + hideCatalogUnderline = false definitions = emptyList() collectionDefinitions = emptyList() _uiState.value = HomeCatalogSettingsUiState() @@ -113,6 +120,7 @@ object HomeCatalogSettingsRepository { preferences.clear() heroEnabled = true hideUnreleasedContent = false + hideCatalogUnderline = false _uiState.value = HomeCatalogSettingsUiState() } @@ -144,6 +152,7 @@ object HomeCatalogSettingsRepository { return HomeCatalogSettingsSnapshot( heroEnabled = heroEnabled, hideUnreleasedContent = hideUnreleasedContent, + hideCatalogUnderline = hideCatalogUnderline, preferences = preferences.mapValues { (_, value) -> HomeCatalogPreference( customTitle = value.customTitle, @@ -172,6 +181,14 @@ object HomeCatalogSettingsRepository { HomeRepository.applyCurrentSettings() } + fun setHideCatalogUnderline(enabled: Boolean) { + ensureLoaded() + if (hideCatalogUnderline == enabled) return + hideCatalogUnderline = enabled + publish() + persist() + } + fun setHeroSourceEnabled(key: String, enabled: Boolean) { updatePreference(key) { preference -> if (!enabled) { @@ -200,6 +217,7 @@ object HomeCatalogSettingsRepository { ensureLoaded() heroEnabled = true hideUnreleasedContent = false + hideCatalogUnderline = false preferences.clear() normalizePreferences() publish() @@ -246,6 +264,7 @@ object HomeCatalogSettingsRepository { if (parsedPayload != null) { heroEnabled = parsedPayload.heroEnabled hideUnreleasedContent = parsedPayload.hideUnreleasedContent + hideCatalogUnderline = parsedPayload.hideCatalogUnderline preferences = parsedPayload.items.associateBy { it.key }.toMutableMap() publish() return @@ -345,6 +364,7 @@ object HomeCatalogSettingsRepository { _uiState.value = HomeCatalogSettingsUiState( heroEnabled = heroEnabled, hideUnreleasedContent = hideUnreleasedContent, + hideCatalogUnderline = hideCatalogUnderline, items = items, ) } @@ -355,6 +375,7 @@ object HomeCatalogSettingsRepository { StoredHomeCatalogSettingsPayload( heroEnabled = heroEnabled, hideUnreleasedContent = hideUnreleasedContent, + hideCatalogUnderline = hideCatalogUnderline, items = preferences.values.sortedBy { it.order }, ), ), @@ -437,6 +458,7 @@ object HomeCatalogSettingsRepository { } return SyncHomeCatalogPayload( hideUnreleasedContent = hideUnreleasedContent, + hideCatalogUnderline = hideCatalogUnderline, items = items, ) } @@ -444,6 +466,7 @@ object HomeCatalogSettingsRepository { fun applyFromRemote(payload: SyncHomeCatalogPayload) { ensureLoaded() hideUnreleasedContent = payload.hideUnreleasedContent + hideCatalogUnderline = payload.hideCatalogUnderline if (payload.items.isNotEmpty()) { val existingHeroState = preferences.mapValues { it.value.heroSourceEnabled } preferences = payload.items.associate { item -> diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt index 5fbf8f7c..bddc4c97 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt @@ -42,6 +42,7 @@ data class SyncCatalogItem( @Serializable data class SyncHomeCatalogPayload( @SerialName("hide_unreleased_content") val hideUnreleasedContent: Boolean = false, + @SerialName("hide_catalog_underline") val hideCatalogUnderline: Boolean = false, val items: List = emptyList(), ) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt index e7561e09..aecd6626 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt @@ -4,11 +4,15 @@ import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.nuvio.app.core.ui.NuvioShelfSection import com.nuvio.app.core.ui.NuvioViewAllPillSize import com.nuvio.app.core.ui.rememberPosterCardStyleUiState +import com.nuvio.app.features.home.HomeCatalogSettingsRepository import com.nuvio.app.features.home.HomeCatalogSection import com.nuvio.app.features.home.MetaPreview import com.nuvio.app.features.home.stableKey @@ -64,6 +68,10 @@ private fun HomeCatalogRowSectionContent( onPosterLongClick: ((MetaPreview) -> Unit)?, ) { val posterCardStyle = rememberPosterCardStyleUiState() + val homeCatalogSettings by remember { + HomeCatalogSettingsRepository.snapshot() + HomeCatalogSettingsRepository.uiState + }.collectAsStateWithLifecycle() NuvioShelfSection( title = section.title, @@ -71,6 +79,7 @@ private fun HomeCatalogRowSectionContent( modifier = modifier, headerHorizontalPadding = sectionPadding, rowContentPadding = PaddingValues(horizontal = sectionPadding), + showHeaderAccent = !homeCatalogSettings.hideCatalogUnderline, onViewAllClick = onViewAllClick, viewAllPillSize = NuvioViewAllPillSize.Compact, key = { item -> item.stableKey() }, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCollectionRowSection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCollectionRowSection.kt index dd053375..da63fe5d 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCollectionRowSection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCollectionRowSection.kt @@ -15,6 +15,8 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale @@ -23,6 +25,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.nuvio.app.core.ui.NuvioShelfSection import com.nuvio.app.core.ui.PosterLandscapeAspectRatio import com.nuvio.app.core.ui.landscapePosterWidth @@ -30,6 +33,7 @@ import com.nuvio.app.core.ui.posterCardClickable import com.nuvio.app.core.ui.rememberPosterCardStyleUiState import com.nuvio.app.features.collection.Collection import com.nuvio.app.features.collection.CollectionFolder +import com.nuvio.app.features.home.HomeCatalogSettingsRepository import com.nuvio.app.features.home.PosterShape @Composable @@ -71,12 +75,18 @@ private fun HomeCollectionRowSectionContent( animateGifs: Boolean, onFolderClick: ((collectionId: String, folderId: String) -> Unit)?, ) { + val homeCatalogSettings by remember { + HomeCatalogSettingsRepository.snapshot() + HomeCatalogSettingsRepository.uiState + }.collectAsStateWithLifecycle() + NuvioShelfSection( title = collection.title, entries = collection.folders, modifier = modifier, headerHorizontalPadding = sectionPadding, rowContentPadding = PaddingValues(horizontal = sectionPadding), + showHeaderAccent = !homeCatalogSettings.hideCatalogUnderline, key = { folder -> "collection_${collection.id}_folder_${folder.id}" }, ) { folder -> CollectionFolderCard( diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/HomescreenSettingsPage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/HomescreenSettingsPage.kt index ee44ba7c..254d49e1 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/HomescreenSettingsPage.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/HomescreenSettingsPage.kt @@ -42,6 +42,8 @@ import nuvio.composeapp.generated.resources.layout_hide_unreleased import nuvio.composeapp.generated.resources.layout_hide_unreleased_sub import nuvio.composeapp.generated.resources.settings_homescreen_empty_message import nuvio.composeapp.generated.resources.settings_homescreen_empty_title +import nuvio.composeapp.generated.resources.settings_homescreen_hide_catalog_underline +import nuvio.composeapp.generated.resources.settings_homescreen_hide_catalog_underline_description import nuvio.composeapp.generated.resources.settings_homescreen_keep_home_focused import nuvio.composeapp.generated.resources.settings_homescreen_limit_reached import nuvio.composeapp.generated.resources.settings_homescreen_no_sources_selected @@ -65,6 +67,7 @@ internal fun LazyListScope.homescreenSettingsContent( isTablet: Boolean, heroEnabled: Boolean, hideUnreleasedContent: Boolean, + hideCatalogUnderline: Boolean, items: List, ) { val selectedHeroSourceCount = items.count { it.heroSourceEnabled } @@ -98,6 +101,14 @@ internal fun LazyListScope.homescreenSettingsContent( isTablet = isTablet, onCheckedChange = HomeCatalogSettingsRepository::setHideUnreleasedContent, ) + SettingsGroupDivider(isTablet = isTablet) + SettingsSwitchRow( + title = stringResource(Res.string.settings_homescreen_hide_catalog_underline), + description = stringResource(Res.string.settings_homescreen_hide_catalog_underline_description), + checked = hideCatalogUnderline, + isTablet = isTablet, + onCheckedChange = HomeCatalogSettingsRepository::setHideCatalogUnderline, + ) } } } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsFullScreenPages.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsFullScreenPages.kt index cbb6bfa4..45c6edf3 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsFullScreenPages.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsFullScreenPages.kt @@ -78,6 +78,7 @@ fun HomescreenSettingsScreen( isTablet = false, heroEnabled = homescreenSettingsUiState.heroEnabled, hideUnreleasedContent = homescreenSettingsUiState.hideUnreleasedContent, + hideCatalogUnderline = homescreenSettingsUiState.hideCatalogUnderline, items = homescreenSettingsUiState.items, ) } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt index 668a3c2e..4cd95d64 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsScreen.kt @@ -237,6 +237,7 @@ fun SettingsScreen( traktSettingsUiState = traktSettingsUiState, homescreenHeroEnabled = homescreenSettingsUiState.heroEnabled, homescreenHideUnreleasedContent = homescreenSettingsUiState.hideUnreleasedContent, + homescreenHideCatalogUnderline = homescreenSettingsUiState.hideCatalogUnderline, homescreenItems = homescreenSettingsUiState.items, metaScreenSettingsUiState = metaScreenSettingsUiState, continueWatchingPreferencesUiState = continueWatchingPreferencesUiState, @@ -283,6 +284,7 @@ fun SettingsScreen( traktSettingsUiState = traktSettingsUiState, homescreenHeroEnabled = homescreenSettingsUiState.heroEnabled, homescreenHideUnreleasedContent = homescreenSettingsUiState.hideUnreleasedContent, + homescreenHideCatalogUnderline = homescreenSettingsUiState.hideCatalogUnderline, homescreenItems = homescreenSettingsUiState.items, metaScreenSettingsUiState = metaScreenSettingsUiState, continueWatchingPreferencesUiState = continueWatchingPreferencesUiState, @@ -339,6 +341,7 @@ private fun MobileSettingsScreen( traktSettingsUiState: TraktSettingsUiState, homescreenHeroEnabled: Boolean, homescreenHideUnreleasedContent: Boolean, + homescreenHideCatalogUnderline: Boolean, homescreenItems: List, metaScreenSettingsUiState: MetaScreenSettingsUiState, continueWatchingPreferencesUiState: ContinueWatchingPreferencesUiState, @@ -530,6 +533,7 @@ private fun MobileSettingsScreen( isTablet = false, heroEnabled = homescreenHeroEnabled, hideUnreleasedContent = homescreenHideUnreleasedContent, + hideCatalogUnderline = homescreenHideCatalogUnderline, items = homescreenItems, ) SettingsPage.MetaScreen -> metaScreenSettingsContent( @@ -638,6 +642,7 @@ private fun TabletSettingsScreen( traktSettingsUiState: TraktSettingsUiState, homescreenHeroEnabled: Boolean, homescreenHideUnreleasedContent: Boolean, + homescreenHideCatalogUnderline: Boolean, homescreenItems: List, metaScreenSettingsUiState: MetaScreenSettingsUiState, continueWatchingPreferencesUiState: ContinueWatchingPreferencesUiState, @@ -888,6 +893,7 @@ private fun TabletSettingsScreen( isTablet = true, heroEnabled = homescreenHeroEnabled, hideUnreleasedContent = homescreenHideUnreleasedContent, + hideCatalogUnderline = homescreenHideCatalogUnderline, items = homescreenItems, ) SettingsPage.MetaScreen -> metaScreenSettingsContent( diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsSearch.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsSearch.kt index 1f3bafee..381ba569 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsSearch.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/SettingsSearch.kt @@ -588,6 +588,7 @@ internal fun settingsSearchEntries( listOf( PlaybackSearchRow("home-hero", stringResource(Res.string.settings_homescreen_show_hero), stringResource(Res.string.settings_homescreen_show_hero_description)), PlaybackSearchRow("home-hide-unreleased", stringResource(Res.string.layout_hide_unreleased), stringResource(Res.string.layout_hide_unreleased_sub)), + PlaybackSearchRow("home-hide-catalog-underline", stringResource(Res.string.settings_homescreen_hide_catalog_underline), stringResource(Res.string.settings_homescreen_hide_catalog_underline_description)), PlaybackSearchRow("home-hero-sources", stringResource(Res.string.settings_homescreen_section_hero_sources)), PlaybackSearchRow("home-catalogs", stringResource(Res.string.settings_homescreen_section_catalogs)), ).forEach { row ->