From 6b0e70588331500c091e6f1f3c4af2c7b5749375 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Sun, 18 Oct 2026 06:55:37 +0000 Subject: [PATCH] Address review: scale artist title cap and cover it with the scrim --- .../ui/components/HeroDetailScaffold.kt | 2 +- .../ui/library/ArtistDetailScreen.kt | 25 ++++++++++++------- .../ui/downloads/DownloadTreeTest.kt | 23 +++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/subtracks/ui/components/HeroDetailScaffold.kt b/app/src/main/kotlin/com/subtracks/ui/components/HeroDetailScaffold.kt index c835b6f8..99b7d798 100644 --- a/app/src/main/kotlin/com/subtracks/ui/components/HeroDetailScaffold.kt +++ b/app/src/main/kotlin/com/subtracks/ui/components/HeroDetailScaffold.kt @@ -280,7 +280,7 @@ fun HeroHeader( style = MaterialTheme.typography.headlineMedium, textAlign = TextAlign.Center, maxLines = nameMaxLines, - overflow = if (nameMaxLines == Int.MAX_VALUE) TextOverflow.Clip else TextOverflow.Ellipsis, + overflow = TextOverflow.Ellipsis, ) val subtitleIsTarget = onSubtitleClick != null && subtitle.isNotEmpty() && comment.isNullOrBlank() if (subtitleIsTarget) { diff --git a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt index fffb24cc..e7c3c72a 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt @@ -52,7 +52,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -257,8 +256,13 @@ fun ArtistDetailScreen( val albumCount = albums.size.toLong() val displayName = artistName.ifBlank { artist?.name.orEmpty() } val artistType = stringResource(if (isAlbumArtist == true) R.string.artist_type_album_artist else R.string.artist_type_artist) - var titleLineCount by remember { mutableIntStateOf(1) } - val imageTitleTop = ART_HEIGHT - TITLE_INSET - lineHeight * titleLineCount + var titleHeightPx by remember { mutableFloatStateOf(0f) } + val titleHeight = if (titleHeightPx > 0f) with(density) { titleHeightPx.toDp() } else lineHeight + val titleMaxLines = + ((ART_HEIGHT - TITLE_INSET - barHeight - FADE_LEAD) / lineHeight) + .toInt() + .coerceIn(1, ARTIST_NAME_MAX_LINES) + val imageTitleTop = ART_HEIGHT - TITLE_INSET - titleHeight val fadeStartPx = with(density) { (imageTitleTop - barHeight - FADE_LEAD).toPx() } val fadeEndPx = with(density) { (imageTitleTop + lineHeight / 2 - barHeight).toPx() } val barFraction by remember(fadeStartPx, fadeEndPx) { @@ -338,7 +342,7 @@ fun ArtistDetailScreen( Modifier .align(Alignment.BottomStart) .fillMaxWidth() - .height(ART_HEIGHT * 0.4f) + .height(maxOf(ART_HEIGHT * 0.4f, titleHeight + TITLE_INSET * 2)) .graphicsLayer { alpha = nameScrimAlpha } .background( Brush.verticalGradient( @@ -353,8 +357,13 @@ fun ArtistDetailScreen( style = imageNameStyle, color = Color.White, endReserve = SHUFFLE_RESERVE, - modifier = Modifier.align(Alignment.BottomStart).fillMaxWidth().padding(TITLE_INSET), - onLineCountChanged = { titleLineCount = it }, + maxLines = titleMaxLines, + modifier = + Modifier + .align(Alignment.BottomStart) + .fillMaxWidth() + .padding(TITLE_INSET) + .onSizeChanged { titleHeightPx = it.height.toFloat() }, ) FilledIconButton( onClick = onShuffle, @@ -521,9 +530,8 @@ private fun ArtistTitle( style: TextStyle, color: Color, endReserve: Dp, + maxLines: Int, modifier: Modifier = Modifier, - maxLines: Int = ARTIST_NAME_MAX_LINES, - onLineCountChanged: (Int) -> Unit = {}, ) { val measurer = rememberTextMeasurer() val density = LocalDensity.current @@ -534,7 +542,6 @@ private fun ArtistTitle( remember(text, style, fullWidth, reserve, maxLines) { splitTitle(measurer, text, style, fullWidth, reserve, maxLines) } - LaunchedEffect(lines.size) { onLineCountChanged(lines.size) } Column { lines.forEachIndexed { index, line -> Text( diff --git a/app/src/test/kotlin/com/subtracks/ui/downloads/DownloadTreeTest.kt b/app/src/test/kotlin/com/subtracks/ui/downloads/DownloadTreeTest.kt index c80fa3a0..814111f0 100644 --- a/app/src/test/kotlin/com/subtracks/ui/downloads/DownloadTreeTest.kt +++ b/app/src/test/kotlin/com/subtracks/ui/downloads/DownloadTreeTest.kt @@ -37,6 +37,29 @@ class DownloadTreeTest { assertEquals(36L, tree.bytes) } + @Test + fun songsKeepTheOrderTheRepositoryReturns() { + val tree = + buildTree( + listOf( + song("s2", "Two", "ar1", "Artist", "al1", "First", size = 20), + song("s1", "One", "ar1", "Artist", "al1", "First", size = 10), + ), + "Unknown artist", + "Unknown album", + ) + + assertEquals( + listOf("Two", "One"), + tree.artists + .single() + .albums + .single() + .songs + .map { it.title }, + ) + } + @Test fun aSongWithNoArtistOrAlbumIsStillShown() { val tree = buildTree(listOf(song("s1", "One", null, null, null, null, size = 3)), "Unknown artist", "Unknown album")