Preserve episode height and fix title overlay and poster collisions
All checks were successful
review/code-claude Blockers fixed on a159c835, delta reviewed
review/design-claude Blockers fixed on a159c835, delta reviewed
All checks were successful
review/code-claude Blockers fixed on a159c835, delta reviewed
review/design-claude Blockers fixed on a159c835, delta reviewed
This commit is contained in:
parent
6d7513bd0e
commit
a159c835c5
14 changed files with 118 additions and 26 deletions
|
|
@ -32,6 +32,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.tv.material3.Text
|
||||
|
|
@ -110,7 +111,7 @@ fun TitleBackdrop(item: TitleItem, modifier: Modifier = Modifier) {
|
|||
val posterShadow = remember { Shadow(radius = D.posterShadowRadius, offset = DpOffset.Zero.copy(y = D.posterShadowY), color = Color.Black.copy(alpha = D.posterShadowOpacity)) }
|
||||
TitleArtwork(item.poster, (L.heroSheetWidth.value * 2).toInt(), (L.heroSheetHeight.value * 2).toInt(),
|
||||
Modifier.offset(WolfskinTokens.Shell.stageWidth - L.heroSheetWidth - D.heroSheetRight, D.heroSheetTop)
|
||||
.size(L.heroSheetWidth, L.heroSheetHeight).dropShadow(posterShape, posterShadow).clip(posterShape), poster = true)
|
||||
.size(L.heroSheetWidth, L.heroSheetHeight).testTag("title-poster-backdrop").dropShadow(posterShape, posterShadow).clip(posterShape), poster = true)
|
||||
}
|
||||
Box(Modifier.fillMaxSize().background(horizontal))
|
||||
Box(Modifier.fillMaxSize().background(vertical))
|
||||
|
|
@ -136,13 +137,13 @@ fun TitleTileArtwork(item: TitleItem) {
|
|||
val filter = remember { ColorFilter.colorMatrix(ColorMatrix().apply {
|
||||
for (index in 0 until 15) values[index] *= D.tileAmbientBrightness
|
||||
}) }
|
||||
TitleArtwork(item.poster, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter)
|
||||
TitleArtwork(item.poster, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter)
|
||||
val height = D.episodeCardHeight - D.tileSheetInset * 2
|
||||
val shape = remember { RoundedCornerShape(D.tileSheetRadius) }
|
||||
val shadow = remember { Shadow(radius = D.tileShadowRadius, offset = DpOffset.Zero.copy(y = D.tileShadowY), color = Color.Black.copy(alpha = D.tileShadowOpacity)) }
|
||||
TitleArtwork(item.poster, (height.value * 2 * 2 / 3).toInt(), (height.value * 2).toInt(),
|
||||
Modifier.offset(D.tileSheetLeft, D.tileSheetInset).size(height * (2f / 3), height).dropShadow(shape, shadow).clip(shape), poster = true)
|
||||
} else TitleArtwork(item.backdrop, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize())
|
||||
} else TitleArtwork(item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ internal fun TitleMenu(state: TitleState, shell: ShellState) {
|
|||
opacity.animateTo(if (visible) 1f else 0f,
|
||||
tween(motionDuration(if (visible) WolfskinTokens.Motion.base else WolfskinTokens.Motion.captionOut, reduced), easing = WolfskinTokens.Motion.easeOut))
|
||||
}
|
||||
if (visible || opacity.value > 0f) {
|
||||
if ((visible || opacity.value > 0f) && (state.sheet == null || state.sheet == TitleSheet.Menu)) {
|
||||
Box(Modifier.fillMaxSize().background(C.sheetScrim)
|
||||
.clickable { if (visible) state.back(shell) }
|
||||
.focusRequester(focus).onPreviewKeyEvent { event ->
|
||||
|
|
|
|||
|
|
@ -93,7 +93,10 @@ fun TitlePage(state: TitleState, shell: ShellState, modifier: Modifier = Modifie
|
|||
val focus = remember { FocusRequester() }
|
||||
var measuredHeaderHeight by remember(state.data.item.id) { mutableStateOf(L.row_dhead) }
|
||||
val compactHeader = state.data.status == TitleReadStatus.Ready
|
||||
val headerHeight = if (compactHeader) measuredHeaderHeight else L.row_dhead
|
||||
val item = state.data.item
|
||||
val posterFloor = if (item.kind == "movie" && item.poster != null && (item.backdrop == null || item.isPosterBackdrop))
|
||||
D.heroSheetTop + L.heroSheetHeight + D.posterCastGap - L.rowHeadingBand else WolfskinTokens.Shell.zero
|
||||
val headerHeight = if (compactHeader) measuredHeaderHeight.coerceAtLeast(posterFloor) else L.row_dhead
|
||||
LaunchedEffect(state.sheet, shell.navFocused, shell.pickerVisible) {
|
||||
if (state.sheet == null && !shell.navFocused && !shell.pickerVisible) focus.requestFocus()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ internal fun TitleRowPrefetch(data: TitlePageData, row: String?) {
|
|||
queue(data.cast[index].portrait, WolfskinTokens.Image.castRequestWidth, WolfskinTokens.Image.castRequestHeight)
|
||||
"episodes" -> for (index in 0 until minOf(data.episodes.size, WolfskinTokens.Card.tileSlots)) {
|
||||
val item = data.episodes[index]
|
||||
queue(if (item.isPosterBackdrop) item.poster else item.backdrop, (WolfskinTokens.Title.episodeCardWidth.value * 2).toInt(), (WolfskinTokens.Title.episodeCardHeight.value * 2).toInt())
|
||||
queue(if (item.isPosterBackdrop) item.poster else item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight)
|
||||
}
|
||||
"related" -> for (index in 0 until minOf(data.related.size, WolfskinTokens.Card.posterSlots))
|
||||
queue(data.related[index].poster, WolfskinTokens.Image.posterRequestWidth, WolfskinTokens.Image.posterRequestHeight, true)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class TitleState(
|
|||
var sheetIndex by mutableStateOf(0)
|
||||
private var mediaInfoFromMenu = false
|
||||
val menuOptions: List<TitleOption> by derivedStateOf { buildList {
|
||||
if (target != null) add(TitleOption("info", "Media info", "more", icon = false))
|
||||
if (target != null) add(TitleOption("info", "Media info", "", icon = false))
|
||||
if (data.connection == TitleConnection.SignedIn && data.requestsAllowed) {
|
||||
add(TitleOption("add", "Add for someone", "users", icon = false))
|
||||
}
|
||||
|
|
@ -72,6 +72,7 @@ class TitleState(
|
|||
if (!pendingSubtitle) subtitleIndex = value.selectedSubtitle
|
||||
if (row !in rows) { row = "header"; column = 0 }
|
||||
column = column.coerceAtMost(rowSize(row).minus(1).coerceAtLeast(0))
|
||||
if (sheet == TitleSheet.Menu && menuOptions.isEmpty()) sheet = null
|
||||
}
|
||||
|
||||
/** Pointer focus and D-pad use the same row memory. */
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ object WolfskinTokens {
|
|||
const val heroRequestHeight = 1080
|
||||
const val heroPosterRequestWidth = 420
|
||||
const val heroPosterRequestHeight = 630
|
||||
const val episodeRequestWidth = 400
|
||||
const val episodeRequestWidth = 448
|
||||
const val episodeRequestHeight = 280
|
||||
const val castRequestWidth = 200
|
||||
const val castRequestHeight = 200
|
||||
|
|
@ -452,9 +452,10 @@ object WolfskinTokens {
|
|||
}
|
||||
object Title {
|
||||
val episodeCardWidth = 224.0.dp
|
||||
val episodeCardHeight = 126.0.dp
|
||||
val episodeCardHeight = 140.0.dp
|
||||
val actionMenuWidth = 260.0.dp
|
||||
val seriesHeaderGap = 20.0.dp
|
||||
val posterCastGap = 10.0.dp
|
||||
val lineGap = 11.0.dp
|
||||
val lineLift = -2.0.dp
|
||||
val overviewGap = 17.0.dp
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class WolfskinImagesTest {
|
|||
Surface("grid/Home/Discover/person poster", 256, 384, "w342"),
|
||||
Surface("Home tile", 400, 225, "w780"),
|
||||
Surface("Home wide", 544, 306, "w780"),
|
||||
Surface("episode still", 400, 280, "w780"),
|
||||
Surface("episode still", 448, 280, "w780"),
|
||||
Surface("cast portrait", 200, 200, "w342"),
|
||||
Surface("person portrait", 240, 240, "w342"),
|
||||
Surface("hero poster", 420, 630, "w342", true),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue