This commit is contained in:
ponzischeme89
2026-08-21 12:12:03 +12:00
parent 48043dbae2
commit 243b7c8b90
5 changed files with 71 additions and 50 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ val projectNoticeText =
// A release workflow can derive the app version from its Git tag without editing the // A release workflow can derive the app version from its Git tag without editing the
// source tree. Local builds keep using the checked-in default. // source tree. Local builds keep using the checked-in default.
val defaultVersionName = "0.2.87" val defaultVersionName = "0.2.88"
val membyVersionName: String = val membyVersionName: String =
(project.findProperty("memby.versionName") as String?) (project.findProperty("memby.versionName") as String?)
?.trim() ?.trim()
@@ -1124,9 +1124,9 @@ internal fun MetadataHero(
.clipToBounds() .clipToBounds()
.background( .background(
Brush.verticalGradient( Brush.verticalGradient(
0f to MembySurface.copy(alpha = 0.52f), 0f to MembySurface.copy(alpha = 0.68f),
0.72f to MembySurface.copy(alpha = 0.30f), 0.72f to MembySurface.copy(alpha = 0.46f),
1f to Color.Transparent, 1f to MembySurface.copy(alpha = 0.16f),
), ),
), ),
) { ) {
@@ -166,9 +166,9 @@ internal fun homeHeaderHeight(viewportHeight: Dp, showHero: Boolean): Dp =
(viewportHeight * 0.46f).coerceIn(232.dp, 300.dp) (viewportHeight * 0.46f).coerceIn(232.dp, 300.dp)
} else { } else {
// The focused metadata surface is also the clean upper boundary for shelves as // The focused metadata surface is also the clean upper boundary for shelves as
// they move vertically. About 20dp more coverage at common TV heights keeps a // they move vertically. Give it a little more room than the cinematic hero so the
// departing card's last text line from being exposed without costing another row. // title, ratings and overview read as one persistent browse panel.
(viewportHeight * 0.46f).coerceIn(240.dp, 320.dp) (viewportHeight * 0.48f).coerceIn(250.dp, 330.dp)
} }
private val LazyListStateMapSaver: Saver<MutableMap<String, LazyListState>, Any> = listSaver( private val LazyListStateMapSaver: Saver<MutableMap<String, LazyListState>, Any> = listSaver(
@@ -12,8 +12,10 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@@ -33,6 +35,7 @@ import androidx.tv.material3.Text
import com.github.takahirom.roborazzi.captureRoboImage import com.github.takahirom.roborazzi.captureRoboImage
import com.ponzischeme89.memby.ServiceLocator import com.ponzischeme89.memby.ServiceLocator
import com.ponzischeme89.memby.data.model.BaseItem import com.ponzischeme89.memby.data.model.BaseItem
import com.ponzischeme89.memby.data.model.MediaRating
import org.junit.Before import org.junit.Before
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Rule import org.junit.Rule
@@ -154,6 +157,11 @@ class HomeMovieHeroScreenshotTest {
2026, 2026,
"Beyond the mapped worlds, one explorer finds an ocean that remembers every visitor.", "Beyond the mapped worlds, one explorer finds an ocean that remembers every visitor.",
8.7, 8.7,
).copy(
membyRatings = listOf(
MediaRating(source = "imdb", name = "IMDb", score = "8.7", scale = "/10"),
MediaRating(source = "tomatoes", name = "Rotten Tomatoes", score = "93", scale = "%"),
),
) )
compose.setContent { compose.setContent {
@@ -165,46 +173,58 @@ class HomeMovieHeroScreenshotTest {
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) )
Column(Modifier.fillMaxSize()) { Row(Modifier.fillMaxSize()) {
MetadataHero( TvNavigationRail(
item = item, selected = BrowseDestination.MOVIES,
loading = false, expanded = true,
sectionLabel = "Movies", navigationFocusRequester = remember { FocusRequester() },
modifier = Modifier onRailFocusChanged = {},
.height(homeHeaderHeight(540.dp, showHero = false)) onDestinationSelected = {},
.zIndex(1f), activeUsername = "Matt",
calendarEnabled = true,
genresEnabled = true,
) )
Text( Column(Modifier.weight(1f).offset(x = 112.dp)) {
"Matt's Favourites", MetadataHero(
color = Color(0xFFF1F3F4), item = item,
fontSize = 18.sp, loading = false,
modifier = Modifier.padding(start = 36.dp, top = 8.dp, bottom = 10.dp), sectionLabel = "Movies",
) modifier = Modifier
Row( .height(homeHeaderHeight(540.dp, showHero = false))
modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp), .zIndex(1f),
horizontalArrangement = Arrangement.spacedBy(12.dp), )
) { Text(
repeat(5) { index -> "Matt's Favourites",
Column(Modifier.weight(1f)) { color = Color(0xFFF1F3F4),
Box( fontSize = 18.sp,
Modifier modifier = Modifier.padding(start = 36.dp, top = 8.dp, bottom = 10.dp),
.fillMaxWidth() )
.aspectRatio(16f / 9f) Row(
.clip(RoundedCornerShape(7.dp)) modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp),
.background(Color(0xFF27343D)), horizontalArrangement = Arrangement.spacedBy(12.dp),
) ) {
Text( repeat(5) { index ->
"Favourite ${index + 1}", Column(Modifier.weight(1f)) {
color = Color.White, Box(
fontSize = 13.sp, Modifier
modifier = Modifier.padding(top = 6.dp), .fillMaxWidth()
) .aspectRatio(16f / 9f)
Text( .clip(RoundedCornerShape(7.dp))
"2026 1h 47m", .background(Color(0xFF27343D)),
color = Color(0xFF8F9AA3), )
fontSize = 11.sp, Text(
modifier = Modifier.padding(top = 2.dp), "Favourite ${index + 1}",
) color = Color.White,
fontSize = 13.sp,
modifier = Modifier.padding(top = 6.dp),
)
Text(
"2026 • 1h 47m",
color = Color(0xFF8F9AA3),
fontSize = 11.sp,
modifier = Modifier.padding(top = 2.dp),
)
}
} }
} }
} }
@@ -43,12 +43,13 @@ class HomeMovieHeroTest {
} }
@Test @Test
fun `metadata hero adds a modest scalable row boundary`() { fun `metadata hero is slightly taller than the cinematic hero`() {
val compactTvHeight = homeHeaderHeight(540.dp, showHero = false) val compactTvHeight = homeHeaderHeight(540.dp, showHero = false)
assertEquals(248.4f, compactTvHeight.value, 0.01f) assertEquals(259.2f, compactTvHeight.value, 0.01f)
assertTrue(540.dp - compactTvHeight >= 288.dp) assertTrue(compactTvHeight > homeHeaderHeight(540.dp, showHero = true))
assertEquals(320f, homeHeaderHeight(720.dp, showHero = false).value, 0.01f) assertTrue(540.dp - compactTvHeight >= 280.dp)
assertEquals(330f, homeHeaderHeight(720.dp, showHero = false).value, 0.01f)
} }
@Test @Test