ui nits: cover placeholder ratio, now playing scrim/title, add-server keyboard, titlebars, search dismiss, fab icon

- CoverArt: use the thumbnail's intrinsic ratio until the full-res painter loads, so non-square art no longer snaps
- Now Playing: move the top scrim out of the sliding screen into MainNavigation, static under the status bar, fading in as the screen settles at the top
- Now Playing: titlebar shows the playback source (album/playlist name, or Library) instead of "Now playing"
- Add server: keep the test/save bar above the keyboard on first launch
- Titlebars: use the theme default title style instead of headlineMedium
- Library: clicking an item in a searched tab dismisses the search
- Library FAB: use the AutoMirrored Sort icon at 28dp so the glyph reads a little thicker
This commit is contained in:
austinried
2026-10-04 00:29:58 +00:00
parent 2552e1a10c
commit 2e925f2f78
12 changed files with 106 additions and 35 deletions
@@ -13,6 +13,7 @@ import com.subtracks.data.model.ShuffleOrder
import com.subtracks.data.model.SongListItem import com.subtracks.data.model.SongListItem
import com.subtracks.data.prefs.SongSort import com.subtracks.data.prefs.SongSort
import com.subtracks.data.prefs.StarredFilter import com.subtracks.data.prefs.StarredFilter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
@@ -119,6 +120,19 @@ class QueueRepository(
return if (index >= 0) index.toLong() else null return if (index >= 0) index.toLong() else null
} }
suspend fun sourceName(
kind: QueueKind,
sourceId: Long,
refId: String,
): String? {
val library = db.libraryDao()
return when (kind) {
QueueKind.Album -> library.album(sourceId, refId).first()?.name
QueueKind.Playlist -> library.playlist(sourceId, refId).first()?.name
QueueKind.Songs, QueueKind.Song -> null
}
}
private fun songsQuery(refId: String): QueueSongQuery? { private fun songsQuery(refId: String): QueueSongQuery? {
val parts = refId.split("|") val parts = refId.split("|")
if (parts.size != 3) return null if (parts.size != 3) return null
@@ -34,6 +34,7 @@ data class QueueItem(
data class QueueContext( data class QueueContext(
val kind: QueueKind, val kind: QueueKind,
val sourceId: Long,
val refId: String, val refId: String,
) )
@@ -889,9 +890,11 @@ class PlaybackController(
private fun contextAt(position: Long?): QueueContext? { private fun contextAt(position: Long?): QueueContext? {
val entry = position?.let { snapshot?.locate(it)?.first } ?: return null val entry = position?.let { snapshot?.locate(it)?.first } ?: return null
return QueueContext(entry.kind, entry.refId) return QueueContext(entry.kind, entry.sourceId, entry.refId)
} }
suspend fun sourceTitle(context: QueueContext?): String? = context?.let { queueRepository.sourceName(it.kind, it.sourceId, it.refId) }
private fun updateBuffering() { private fun updateBuffering() {
if (player?.isBuffering != true) { if (player?.isBuffering != true) {
bufferingJob?.cancel() bufferingJob?.cancel()
@@ -14,6 +14,7 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState import androidx.compose.foundation.gestures.rememberDraggableState
@@ -23,9 +24,12 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imeAnimationTarget import androidx.compose.foundation.layout.imeAnimationTarget
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.statusBars
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -37,6 +41,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.layout.positionInRoot
@@ -88,6 +94,7 @@ private const val OVERLAY_DURATION_MS = 200
private const val EXPAND_FADE = 0.1f private const val EXPAND_FADE = 0.1f
private const val FLING_VELOCITY = 1000f private const val FLING_VELOCITY = 1000f
private const val MINI_PLAYER_ANIM_MS = 200 private const val MINI_PLAYER_ANIM_MS = 200
private const val SCRIM_FADE_START = 0.6f
private object Routes { private object Routes {
const val LIBRARY = "library" const val LIBRARY = "library"
@@ -163,6 +170,7 @@ private fun MainNavigation() {
} }
val density = LocalDensity.current val density = LocalDensity.current
val navBarInset = with(density) { WindowInsets.navigationBars.getBottom(this).toDp() } val navBarInset = with(density) { WindowInsets.navigationBars.getBottom(this).toDp() }
val statusBarInset = with(density) { WindowInsets.statusBars.getTop(this).toDp() }
val keyboardUp = WindowInsets.imeAnimationTarget.getBottom(density) > 0 val keyboardUp = WindowInsets.imeAnimationTarget.getBottom(density) > 0
val showMiniPlayer = playerVisible && !keyboardUp val showMiniPlayer = playerVisible && !keyboardUp
val bottomInset by animateDpAsState( val bottomInset by animateDpAsState(
@@ -333,6 +341,21 @@ private fun MainNavigation() {
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) )
} }
Box(
modifier =
Modifier
.align(Alignment.TopCenter)
.fillMaxWidth()
.height(statusBarInset + 8.dp)
.graphicsLayer {
alpha = ((nowPlayingProgress - SCRIM_FADE_START) / (1f - SCRIM_FADE_START)).coerceIn(0f, 1f)
}.background(
Brush.verticalGradient(
listOf(Color.Black.copy(alpha = 0.55f), Color.Transparent),
),
),
)
} }
AnimatedVisibility( AnimatedVisibility(
@@ -85,8 +85,16 @@ fun CoverArt(
onError = { failed = true }, onError = { failed = true },
contentScale = ContentScale.Fit, contentScale = ContentScale.Fit,
) )
val thumbnailPainter =
rememberAsyncImagePainter(
model = remember(thumbnailRef) { thumbnailRef?.let { imageRequest(context, it, crossfade = false) } },
contentScale = ContentScale.Fit,
)
BoxWithConstraints(modifier, contentAlignment = Alignment.Center) { BoxWithConstraints(modifier, contentAlignment = Alignment.Center) {
val ratio = painter.intrinsicSize.ratioOrOne() val ratio =
painter.intrinsicSize.ratioOrNull()
?: thumbnailPainter.intrinsicSize.ratioOrNull()
?: 1f
val width = if (ratio > maxWidth.value / maxHeight.value) maxWidth else maxHeight * ratio val width = if (ratio > maxWidth.value / maxHeight.value) maxWidth else maxHeight * ratio
Box(Modifier.size(width, width / ratio).then(frameModifier)) { Box(Modifier.size(width, width / ratio).then(frameModifier)) {
CoverArtContent( CoverArtContent(
@@ -146,7 +154,7 @@ private fun BoxScope.CoverArtContent(
main() main()
} }
private fun Size.ratioOrOne(): Float = if (width > 0f && height > 0f && width.isFinite() && height.isFinite()) width / height else 1f private fun Size.ratioOrNull(): Float? = if (width > 0f && height > 0f && width.isFinite() && height.isFinite()) width / height else null
private fun imageRequest( private fun imageRequest(
context: Context, context: Context,
@@ -166,7 +166,6 @@ fun HeroDetailScaffold(
title = { title = {
Text( Text(
text = title, text = title,
style = MaterialTheme.typography.headlineMedium,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = Modifier.graphicsLayer { alpha = barFraction }, modifier = Modifier.graphicsLayer { alpha = barFraction },
@@ -25,8 +25,8 @@ import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.automirrored.rounded.PlaylistPlay import androidx.compose.material.icons.automirrored.rounded.PlaylistPlay
import androidx.compose.material.icons.filled.Sort
import androidx.compose.material.icons.rounded.Add import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.Album import androidx.compose.material.icons.rounded.Album
import androidx.compose.material.icons.rounded.ArrowDownward import androidx.compose.material.icons.rounded.ArrowDownward
@@ -304,6 +304,13 @@ fun LibraryScreen(
if (search.isNotEmpty()) searchActive = true if (search.isNotEmpty()) searchActive = true
} }
fun dismissSearch() {
if (searchActive) {
searchActive = false
onSearchChange("")
}
}
val density = LocalDensity.current val density = LocalDensity.current
val statusBarTop = with(density) { WindowInsets.statusBars.getTop(this).toDp() } val statusBarTop = with(density) { WindowInsets.statusBars.getTop(this).toDp() }
val filtersActive = listQuery.starred != StarredFilter.Any || search.isNotEmpty() val filtersActive = listQuery.starred != StarredFilter.Any || search.isNotEmpty()
@@ -347,7 +354,10 @@ fun LibraryScreen(
albums, albums,
coverArt, coverArt,
listBottomInset, listBottomInset,
onAlbumClick, {
dismissSearch()
onAlbumClick(it)
},
filtered = filtersActive, filtered = filtersActive,
onClearFilters = onClearFilters, onClearFilters = onClearFilters,
resetKey = resetKey, resetKey = resetKey,
@@ -361,7 +371,10 @@ fun LibraryScreen(
artists, artists,
coverArt, coverArt,
listBottomInset, listBottomInset,
onArtistClick, {
dismissSearch()
onArtistClick(it)
},
filtered = filtersActive, filtered = filtersActive,
onClearFilters = onClearFilters, onClearFilters = onClearFilters,
resetKey = resetKey, resetKey = resetKey,
@@ -375,7 +388,10 @@ fun LibraryScreen(
songs, songs,
coverArt, coverArt,
listBottomInset, listBottomInset,
onSongClick, {
dismissSearch()
onSongClick(it)
},
playingSongId, playingSongId,
filtered = filtersActive, filtered = filtersActive,
onClearFilters = onClearFilters, onClearFilters = onClearFilters,
@@ -390,7 +406,10 @@ fun LibraryScreen(
playlists, playlists,
coverArt, coverArt,
listBottomInset, listBottomInset,
onPlaylistClick, {
dismissSearch()
onPlaylistClick(it)
},
filtered = filtersActive, filtered = filtersActive,
onClearFilters = onClearFilters, onClearFilters = onClearFilters,
resetKey = resetKey, resetKey = resetKey,
@@ -460,7 +479,11 @@ fun LibraryScreen(
modifier = Modifier.align(Alignment.BottomEnd).padding(end = 16.dp, bottom = tabBarHeight + 16.dp), modifier = Modifier.align(Alignment.BottomEnd).padding(end = 16.dp, bottom = tabBarHeight + 16.dp),
) { ) {
Box { Box {
Icon(Icons.Filled.Sort, contentDescription = "List options") Icon(
Icons.AutoMirrored.Filled.Sort,
contentDescription = "List options",
modifier = Modifier.size(28.dp),
)
if (filtersActive) { if (filtersActive) {
Box( Box(
modifier = modifier =
@@ -7,13 +7,11 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
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.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.ArrowBack
@@ -45,11 +43,11 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.PlatformTextStyle
@@ -61,6 +59,7 @@ import coil3.SingletonImageLoader
import coil3.compose.LocalPlatformContext import coil3.compose.LocalPlatformContext
import coil3.request.ImageRequest import coil3.request.ImageRequest
import com.subtracks.data.model.CoverArtRef import com.subtracks.data.model.CoverArtRef
import com.subtracks.data.model.QueueKind
import com.subtracks.playback.PlaybackController import com.subtracks.playback.PlaybackController
import com.subtracks.playback.PlaybackState import com.subtracks.playback.PlaybackState
import com.subtracks.playback.RepeatMode import com.subtracks.playback.RepeatMode
@@ -83,6 +82,11 @@ fun NowPlayingRoute(
val context = LocalPlatformContext.current val context = LocalPlatformContext.current
val art = controller.coverArt(state.item) val art = controller.coverArt(state.item)
val thumbnail = controller.coverArt(state.item, thumbnail = true) val thumbnail = controller.coverArt(state.item, thumbnail = true)
val queueContext = state.context
val fallbackTitle = if (queueContext?.kind == QueueKind.Album) state.item?.album.orEmpty() else "Library"
val sourceTitle by produceState<String>(initialValue = fallbackTitle, queueContext) {
value = controller.sourceTitle(queueContext) ?: fallbackTitle
}
LaunchedEffect(state.item?.id, state.hasNext) { LaunchedEffect(state.item?.id, state.hasNext) {
if (!state.hasNext) return@LaunchedEffect if (!state.hasNext) return@LaunchedEffect
controller.upcomingCoverArt(thumbnail = true)?.let { ArtworkSeedCache.prefetch(context, it) } controller.upcomingCoverArt(thumbnail = true)?.let { ArtworkSeedCache.prefetch(context, it) }
@@ -90,6 +94,7 @@ fun NowPlayingRoute(
} }
NowPlayingScreen( NowPlayingScreen(
state = state, state = state,
title = sourceTitle,
coverArt = art, coverArt = art,
thumbnailRef = thumbnail, thumbnailRef = thumbnail,
artwork = rememberArtworkColors(thumbnail ?: art), artwork = rememberArtworkColors(thumbnail ?: art),
@@ -123,6 +128,7 @@ private fun prefetchImage(
@Composable @Composable
fun NowPlayingScreen( fun NowPlayingScreen(
state: PlaybackState, state: PlaybackState,
title: String,
coverArt: CoverArtRef?, coverArt: CoverArtRef?,
artwork: ArtworkColors?, artwork: ArtworkColors?,
onBack: () -> Unit, onBack: () -> Unit,
@@ -157,19 +163,6 @@ fun NowPlayingScreen(
scrollPx = { 0f }, scrollPx = { 0f },
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) )
val statusBarDp = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
Box(
modifier =
Modifier
.align(Alignment.TopStart)
.fillMaxWidth()
.height(statusBarDp + 8.dp)
.background(
Brush.verticalGradient(
listOf(Color.Black.copy(alpha = 0.55f), Color.Transparent),
),
),
)
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
containerColor = Color.Transparent, containerColor = Color.Transparent,
@@ -177,8 +170,7 @@ fun NowPlayingScreen(
TopAppBar( TopAppBar(
title = { title = {
Text( Text(
text = "Now playing", text = title,
style = MaterialTheme.typography.headlineMedium,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
@@ -336,7 +336,7 @@ fun QueueScreen(
modifier = modifier, modifier = modifier,
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text("Queue", style = MaterialTheme.typography.headlineMedium) }, title = { Text("Queue") },
navigationIcon = { navigationIcon = {
IconButton(onClick = onBack) { IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back") Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back")
@@ -2,9 +2,11 @@ package com.subtracks.ui.settings
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
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.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@@ -56,7 +58,7 @@ fun AddSourceRoute(
) )
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable @Composable
fun AddSourceScreen( fun AddSourceScreen(
state: AddSourceState, state: AddSourceState,
@@ -74,7 +76,7 @@ fun AddSourceScreen(
modifier = modifier, modifier = modifier,
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text("Add server", style = MaterialTheme.typography.headlineMedium) }, title = { Text("Add server") },
navigationIcon = { navigationIcon = {
if (onBack != null) { if (onBack != null) {
IconButton(onClick = onBack) { IconButton(onClick = onBack) {
@@ -86,7 +88,12 @@ fun AddSourceScreen(
}, },
bottomBar = { bottomBar = {
Row( Row(
modifier = Modifier.fillMaxWidth().navigationBarsPadding().padding(16.dp), modifier =
Modifier
.fillMaxWidth()
.imePadding()
.navigationBarsPadding()
.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.End), horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.End),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
@@ -97,7 +97,7 @@ fun SettingsScreen(
modifier = modifier, modifier = modifier,
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text("Settings", style = MaterialTheme.typography.headlineMedium) }, title = { Text("Settings") },
navigationIcon = { navigationIcon = {
IconButton(onClick = onBack) { IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back") Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back")
@@ -78,7 +78,7 @@ class PlaybackControllerTest {
await { handle.operations.contains("play") } await { handle.operations.contains("play") }
assertEquals(51, handle.itemCount) assertEquals(51, handle.itemCount)
assertEquals(QueueContext(QueueKind.Songs, ""), controller.state.value.context) assertEquals(QueueContext(QueueKind.Songs, 1, ""), controller.state.value.context)
assertTrue(controller.state.value.hasNext) assertTrue(controller.state.value.hasNext)
assertTrue(controller.state.value.hasPrevious) assertTrue(controller.state.value.hasPrevious)
} }
@@ -305,7 +305,7 @@ class PlaybackControllerTest {
controller.playAlbum(1, "al1", 0) controller.playAlbum(1, "al1", 0)
await { controller.state.value.item != null } await { controller.state.value.item != null }
assertEquals(QueueContext(QueueKind.Album, "al1"), controller.state.value.context) assertEquals(QueueContext(QueueKind.Album, 1, "al1"), controller.state.value.context)
assertTrue(controller.state.value.isPlaying) assertTrue(controller.state.value.isPlaying)
assertTrue(controller.state.value.hasNext) assertTrue(controller.state.value.hasNext)
assertTrue(controller.state.value.hasPrevious) assertTrue(controller.state.value.hasPrevious)
@@ -370,6 +370,7 @@ class AppScreenshotTest {
SubtracksTheme { SubtracksTheme {
NowPlayingScreen( NowPlayingScreen(
state = Fixtures.playbackState(), state = Fixtures.playbackState(),
title = "Kid A",
coverArt = CoverArtRef("art-al-kid-a", "test:art-al-kid-a"), coverArt = CoverArtRef("art-al-kid-a", "test:art-al-kid-a"),
artwork = artworkColorsFromSeed(Color.rgb(120, 80, 200)), artwork = artworkColorsFromSeed(Color.rgb(120, 80, 200)),
onBack = {}, onBack = {},
@@ -392,6 +393,7 @@ class AppScreenshotTest {
SubtracksTheme { SubtracksTheme {
NowPlayingScreen( NowPlayingScreen(
state = Fixtures.playbackState().copy(shuffle = true, repeat = RepeatMode.One), state = Fixtures.playbackState().copy(shuffle = true, repeat = RepeatMode.One),
title = "Kid A",
coverArt = CoverArtRef("art-al-kid-a", "test:art-al-kid-a"), coverArt = CoverArtRef("art-al-kid-a", "test:art-al-kid-a"),
artwork = artworkColorsFromSeed(Color.rgb(120, 80, 200)), artwork = artworkColorsFromSeed(Color.rgb(120, 80, 200)),
onBack = {}, onBack = {},