mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
refactor(tv): extract hero backdrop and simplify gradient drawing
Split the hero backdrop (image + gradient overlays) into TvHomeHeroBackdrop, rendered behind the home content. Replace nested Box/background gradient approach with drawWithContent for better composability. Clean up unused imports across TvHomeScreen, TvFocusedItemHero, and TvHomeContent.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package hu.bbara.purefin.ui.screen.home
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -10,11 +10,12 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import hu.bbara.purefin.core.model.LibraryUiModel
|
||||
import hu.bbara.purefin.core.model.MediaUiModel
|
||||
import hu.bbara.purefin.core.model.MovieUiModel
|
||||
import hu.bbara.purefin.core.model.LibraryUiModel
|
||||
import hu.bbara.purefin.ui.screen.home.components.TvFocusedItemHero
|
||||
import hu.bbara.purefin.ui.screen.home.components.TvHomeContent
|
||||
import hu.bbara.purefin.ui.screen.home.components.TvHomeHeroBackdrop
|
||||
import java.util.UUID
|
||||
|
||||
@Composable
|
||||
@@ -30,11 +31,13 @@ fun TvHomeScreen(
|
||||
val focusedMediaUiModel = remember { mutableStateOf<MediaUiModel>(MovieUiModel.createPlaceholder()) }
|
||||
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
modifier = modifier.fillMaxSize(),
|
||||
color = scheme.background
|
||||
) {
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
TvHomeHeroBackdrop(
|
||||
backdropImageUrl = focusedMediaUiModel.value.backdropImageUrl
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
@@ -56,4 +59,5 @@ fun TvHomeScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ package hu.bbara.purefin.ui.screen.home.components
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
@@ -16,6 +14,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.testTag
|
||||
@@ -31,40 +30,34 @@ internal const val TvHomeHeroTitleTag = "tv-home-hero-title"
|
||||
internal const val TvHomeHeroProgressLabelTag = "tv-home-hero-progress-label"
|
||||
|
||||
private const val TvHomeHeroAnimationMillis = 180
|
||||
// Half the screen for the billboard, half for the content rows. Tuned so both
|
||||
// the hero block and the first focused row fit on a 540dp-tall (1080p xhdpi) TV.
|
||||
// The billboard backdrop covers the top portion of the home screen so the hero
|
||||
// text sits at the bottom of the backdrop and the content rows begin below it.
|
||||
internal const val TvHomeHeroHeightFraction = 0.45f
|
||||
internal const val TvHomeBackdropOffset = 0.20f
|
||||
|
||||
/**
|
||||
* The home screen background image plus the darkening gradients that keep the
|
||||
* hero text readable. Drawn behind the home content and sized to the top
|
||||
* [TvHomeHeroHeightFraction] of the screen.
|
||||
*/
|
||||
@Composable
|
||||
internal fun TvFocusedItemHero(
|
||||
item: MediaUiModel,
|
||||
internal fun TvHomeHeroBackdrop(
|
||||
backdropImageUrl: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
heightFraction: Float = TvHomeHeroHeightFraction,
|
||||
heightFraction: Float = TvHomeHeroHeightFraction + TvHomeBackdropOffset,
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
Box(
|
||||
Crossfade(
|
||||
targetState = backdropImageUrl,
|
||||
animationSpec = tween(durationMillis = TvHomeHeroAnimationMillis),
|
||||
label = "tv-home-hero-backdrop",
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(heightFraction)
|
||||
.background(scheme.background)
|
||||
) {
|
||||
Crossfade(
|
||||
targetState = item.backdropImageUrl,
|
||||
animationSpec = tween(durationMillis = TvHomeHeroAnimationMillis),
|
||||
label = "tv-home-hero-background"
|
||||
) { imageUrl ->
|
||||
PurefinAsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
}
|
||||
.drawWithContent {
|
||||
drawContent()
|
||||
// Darken the left side so the text block stays readable over any backdrop.
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
drawRect(
|
||||
Brush.horizontalGradient(
|
||||
colorStops = arrayOf(
|
||||
0.0f to scheme.background.copy(alpha = 0.86f),
|
||||
@@ -74,12 +67,8 @@ internal fun TvFocusedItemHero(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
// Strong bottom fade so the title and metadata are legible.
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
drawRect(
|
||||
Brush.verticalGradient(
|
||||
colorStops = arrayOf(
|
||||
0.0f to scheme.background.copy(alpha = 0f),
|
||||
@@ -89,11 +78,31 @@ internal fun TvFocusedItemHero(
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { imageUrl ->
|
||||
PurefinAsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun TvFocusedItemHero(
|
||||
item: MediaUiModel,
|
||||
modifier: Modifier = Modifier,
|
||||
heightFraction: Float = TvHomeHeroHeightFraction,
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
Crossfade(
|
||||
targetState = item,
|
||||
animationSpec = tween(durationMillis = TvHomeHeroAnimationMillis),
|
||||
label = "tv-home-hero-content"
|
||||
label = "tv-home-hero-content",
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(heightFraction)
|
||||
) { hero ->
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Bottom,
|
||||
@@ -129,7 +138,6 @@ internal fun TvFocusedItemHero(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
package hu.bbara.purefin.ui.screen.home.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.LocalBringIntoViewSpec
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
@@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -42,7 +40,6 @@ fun TvHomeContent(
|
||||
contentPadding: PaddingValues = PaddingValues(bottom = 32.dp),
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
val topOffsetPx = with(LocalDensity.current) { TvHomeFocusedItemTopOffset.toPx() }
|
||||
val hasContinueWatching = continueWatching.isNotEmpty()
|
||||
val hasNextUp = nextUp.isNotEmpty()
|
||||
@@ -65,7 +62,6 @@ fun TvHomeContent(
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
.focusRequester(initialFocusRequester),
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
contentPadding = contentPadding
|
||||
|
||||
Reference in New Issue
Block a user