mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-08-04 18:42:34 +00:00
feat(settings): add cinematic background toggle to settings
This commit is contained in:
parent
fe04d6cf72
commit
a972630bdc
3 changed files with 84 additions and 1 deletions
|
|
@ -38,10 +38,17 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.nuvio.app.core.ui.NuvioBackButton
|
||||
import com.nuvio.app.core.ui.TraktListPickerDialog
|
||||
import com.nuvio.app.core.ui.nuvioPlatformExtraBottomPadding
|
||||
|
|
@ -435,11 +442,31 @@ fun MetaDetailsScreen(
|
|||
val isTablet = maxWidth >= 720.dp
|
||||
val contentHorizontalPadding = if (isTablet) 32.dp else 18.dp
|
||||
val contentMaxWidth = detailTabletContentMaxWidth(maxWidth, isTablet)
|
||||
val cinematicEnabled = metaScreenSettingsUiState.cinematicBackground
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (cinematicEnabled) {
|
||||
val backdropUrl = meta.background ?: meta.poster
|
||||
if (backdropUrl != null) {
|
||||
AsyncImage(
|
||||
model = backdropUrl,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.blur(30.dp),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background.copy(alpha = 0.92f)),
|
||||
)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.zIndex(1f)
|
||||
.verticalScroll(scrollState),
|
||||
) {
|
||||
DetailHero(
|
||||
|
|
@ -524,13 +551,36 @@ fun MetaDetailsScreen(
|
|||
}
|
||||
}
|
||||
|
||||
if (cinematicEnabled && heroHeightPx > 0) {
|
||||
val blendColor = MaterialTheme.colorScheme.background
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.zIndex(0.5f)
|
||||
.fillMaxWidth()
|
||||
.height(132.dp)
|
||||
.graphicsLayer {
|
||||
translationY = heroHeightPx.toFloat() - scrollState.value
|
||||
}
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
blendColor.copy(alpha = 0.98f),
|
||||
blendColor.copy(alpha = 0.84f),
|
||||
blendColor.copy(alpha = 0.52f),
|
||||
Color.Transparent,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (headerProgress <= 0.05f) {
|
||||
NuvioBackButton(
|
||||
onClick = onBack,
|
||||
modifier = Modifier.padding(
|
||||
start = 12.dp,
|
||||
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 8.dp,
|
||||
),
|
||||
).zIndex(2f),
|
||||
containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
|
||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
|
|
@ -542,6 +592,7 @@ fun MetaDetailsScreen(
|
|||
progress = headerProgress,
|
||||
onBack = onBack,
|
||||
onToggleSaved = toggleSaved,
|
||||
modifier = Modifier.zIndex(2f),
|
||||
)
|
||||
|
||||
selectedEpisodeForActions?.let { selectedEpisode ->
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ data class MetaScreenSectionItem(
|
|||
|
||||
data class MetaScreenSettingsUiState(
|
||||
val items: List<MetaScreenSectionItem> = emptyList(),
|
||||
val cinematicBackground: Boolean = false,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
|
@ -43,6 +44,7 @@ private data class StoredMetaScreenSectionPreference(
|
|||
@Serializable
|
||||
private data class StoredMetaScreenSettingsPayload(
|
||||
val items: List<StoredMetaScreenSectionPreference> = emptyList(),
|
||||
val cinematicBackground: Boolean = false,
|
||||
)
|
||||
|
||||
private data class MetaScreenSectionDefinition(
|
||||
|
|
@ -115,6 +117,7 @@ object MetaScreenSettingsRepository {
|
|||
|
||||
private var hasLoaded = false
|
||||
private var preferences: MutableMap<MetaScreenSectionKey, StoredMetaScreenSectionPreference> = mutableMapOf()
|
||||
private var cinematicBackground: Boolean = false
|
||||
|
||||
fun ensureLoaded() {
|
||||
if (hasLoaded) return
|
||||
|
|
@ -126,6 +129,7 @@ object MetaScreenSettingsRepository {
|
|||
json.decodeFromString<StoredMetaScreenSettingsPayload>(payload)
|
||||
}.getOrNull()
|
||||
if (parsed != null) {
|
||||
cinematicBackground = parsed.cinematicBackground
|
||||
preferences = parsed.items.mapNotNull { item ->
|
||||
val key = runCatching { MetaScreenSectionKey.valueOf(item.key) }.getOrNull() ?: return@mapNotNull null
|
||||
key to item
|
||||
|
|
@ -141,13 +145,22 @@ object MetaScreenSettingsRepository {
|
|||
fun onProfileChanged() {
|
||||
hasLoaded = false
|
||||
preferences.clear()
|
||||
cinematicBackground = false
|
||||
_uiState.value = MetaScreenSettingsUiState()
|
||||
ensureLoaded()
|
||||
}
|
||||
|
||||
fun setCinematicBackground(enabled: Boolean) {
|
||||
ensureLoaded()
|
||||
cinematicBackground = enabled
|
||||
publish()
|
||||
persist()
|
||||
}
|
||||
|
||||
fun clearLocalState() {
|
||||
hasLoaded = false
|
||||
preferences.clear()
|
||||
cinematicBackground = false
|
||||
_uiState.value = MetaScreenSettingsUiState()
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +173,7 @@ object MetaScreenSettingsRepository {
|
|||
fun resetToDefaults() {
|
||||
ensureLoaded()
|
||||
preferences.clear()
|
||||
cinematicBackground = false
|
||||
normalizePreferences()
|
||||
publish()
|
||||
persist()
|
||||
|
|
@ -221,6 +235,7 @@ object MetaScreenSettingsRepository {
|
|||
order = preference?.order ?: 0,
|
||||
)
|
||||
},
|
||||
cinematicBackground = cinematicBackground,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +244,7 @@ object MetaScreenSettingsRepository {
|
|||
json.encodeToString(
|
||||
StoredMetaScreenSettingsPayload(
|
||||
items = preferences.values.sortedBy { it.order },
|
||||
cinematicBackground = cinematicBackground,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,22 @@ internal fun LazyListScope.metaScreenSettingsContent(
|
|||
isTablet: Boolean,
|
||||
uiState: MetaScreenSettingsUiState,
|
||||
) {
|
||||
item {
|
||||
SettingsSection(
|
||||
title = "APPEARANCE",
|
||||
isTablet = isTablet,
|
||||
) {
|
||||
SettingsGroup(isTablet = isTablet) {
|
||||
SettingsSwitchRow(
|
||||
title = "Cinematic Background",
|
||||
description = "Blurred backdrop behind content, similar to stream screen.",
|
||||
checked = uiState.cinematicBackground,
|
||||
isTablet = isTablet,
|
||||
onCheckedChange = { MetaScreenSettingsRepository.setCinematicBackground(it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
SettingsSection(
|
||||
title = "SECTIONS",
|
||||
|
|
|
|||
Loading…
Reference in a new issue