diff --git a/app/src/main/kotlin/com/subtracks/ui/AppRoot.kt b/app/src/main/kotlin/com/subtracks/ui/AppRoot.kt index 55a5101c..0c85f80f 100644 --- a/app/src/main/kotlin/com/subtracks/ui/AppRoot.kt +++ b/app/src/main/kotlin/com/subtracks/ui/AppRoot.kt @@ -56,8 +56,7 @@ import com.subtracks.ui.playback.NowPlayingRoute import com.subtracks.ui.playback.QueueRoute import com.subtracks.ui.settings.AddSourceRoute import com.subtracks.ui.settings.SettingsRoute -import com.subtracks.ui.theme.LocalPlayerSurfaceColor -import com.subtracks.ui.theme.playerSurfaceColor +import com.subtracks.ui.theme.LocalPlayerArtwork import com.subtracks.ui.theme.rememberArtworkColors import kotlinx.coroutines.Job import kotlinx.coroutines.flow.SharingStarted @@ -148,11 +147,11 @@ private fun MainNavigation() { } val miniArt = playbackController.coverArt(playback.item, thumbnail = true) val miniArtwork = rememberArtworkColors(miniArt) - val playerSurface = playerSurfaceColor(miniArtwork) + val libraryArtwork = miniArtwork.takeIf { miniArt != null } val density = LocalDensity.current val navBarInset = with(density) { WindowInsets.navigationBars.getBottom(this).toDp() } - CompositionLocalProvider(LocalPlayerSurfaceColor provides playerSurface) { + CompositionLocalProvider(LocalPlayerArtwork provides libraryArtwork) { Box(Modifier.fillMaxSize()) { Column(Modifier.fillMaxSize()) { NavHost( diff --git a/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt index 7fad1a4e..e1f8c62d 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt @@ -51,7 +51,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.isSpecified +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.lerp import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -69,7 +69,9 @@ import com.subtracks.data.model.Artist import com.subtracks.data.model.CoverArtRef import com.subtracks.data.model.Playlist import com.subtracks.data.model.SongListItem -import com.subtracks.ui.theme.LocalPlayerSurfaceColor +import com.subtracks.ui.theme.HeroGradient +import com.subtracks.ui.theme.LocalPlayerArtwork +import com.subtracks.ui.theme.playerSurfaceColor import org.koin.compose.viewmodel.koinViewModel import kotlin.math.abs import kotlin.math.roundToInt @@ -169,10 +171,8 @@ fun LibraryScreen( val titleFraction = scrollBehavior.state.collapsedFraction val statusBarTop = with(density) { WindowInsets.statusBars.getTop(this).toDp() } - val headerColor = - LocalPlayerSurfaceColor.current.let { - if (it.isSpecified) it else MaterialTheme.colorScheme.surfaceContainerHigh - } + val artwork = LocalPlayerArtwork.current + val headerColor = artwork?.let(::playerSurfaceColor) ?: MaterialTheme.colorScheme.surfaceContainerHigh Column( modifier = @@ -213,18 +213,28 @@ fun LibraryScreen( syncing = syncing, onSync = onSync, onOpenSettings = onOpenSettings, + selectedColor = headerColor, ) } - HorizontalPager( - state = pagerState, - modifier = Modifier.fillMaxWidth().weight(1f), - ) { page -> - when (LibraryTab.entries[page]) { - LibraryTab.Albums -> AlbumsContent(albums, coverArt, bottomInset, onAlbumClick) - LibraryTab.Artists -> ArtistsContent(artists, coverArt, bottomInset, onArtistClick) - LibraryTab.Songs -> SongsContent(songs, coverArt, bottomInset, onSongClick, playingSongId) - LibraryTab.Playlists -> PlaylistsContent(playlists, coverArt, bottomInset, onPlaylistClick) + Box(Modifier.fillMaxWidth().weight(1f)) { + if (artwork != null) { + HeroGradient( + colors = artwork, + scrollPx = { 0f }, + modifier = Modifier.fillMaxSize(), + ) + } + HorizontalPager( + state = pagerState, + modifier = Modifier.fillMaxSize(), + ) { page -> + when (LibraryTab.entries[page]) { + LibraryTab.Albums -> AlbumsContent(albums, coverArt, bottomInset, onAlbumClick) + LibraryTab.Artists -> ArtistsContent(artists, coverArt, bottomInset, onArtistClick) + LibraryTab.Songs -> SongsContent(songs, coverArt, bottomInset, onSongClick, playingSongId) + LibraryTab.Playlists -> PlaylistsContent(playlists, coverArt, bottomInset, onPlaylistClick) + } } } } @@ -238,6 +248,7 @@ private fun LibraryTabs( syncing: Boolean, onSync: () -> Unit, onOpenSettings: () -> Unit, + selectedColor: Color, ) { val iconFadeThreshold = 0.65f val indicatorStretch = 18.dp @@ -281,6 +292,7 @@ private fun LibraryTabs( ((iconFadeThreshold - abs(position - index)) / iconFadeThreshold) .coerceIn(0f, 1f), onClick = { onTabSelected(tab) }, + selectedColor = selectedColor, modifier = Modifier.onGloballyPositioned { coordinates -> bounds[index] = coordinates.boundsInParent() @@ -318,9 +330,10 @@ private fun TabButton( tab: LibraryTab, progress: Float, onClick: () -> Unit, + selectedColor: Color, modifier: Modifier = Modifier, ) { - val content = lerp(MaterialTheme.colorScheme.onBackground, MaterialTheme.colorScheme.background, progress) + val content = lerp(MaterialTheme.colorScheme.onBackground, selectedColor, progress) Box( modifier = modifier diff --git a/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt b/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt index fa9ae453..ae29f0b5 100644 --- a/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt +++ b/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt @@ -206,7 +206,7 @@ fun ArtworkTheme( } } -val LocalPlayerSurfaceColor = compositionLocalOf { Color.Unspecified } +val LocalPlayerArtwork = compositionLocalOf { null } fun playerSurfaceColor(artwork: ArtworkColors): Color = lerp(artwork.scheme.surfaceContainerHigh, artwork.gradientHigh, 0.5f) diff --git a/app/src/test/kotlin/com/subtracks/ui/AppScreenshotTest.kt b/app/src/test/kotlin/com/subtracks/ui/AppScreenshotTest.kt index 93e49977..3643292d 100644 --- a/app/src/test/kotlin/com/subtracks/ui/AppScreenshotTest.kt +++ b/app/src/test/kotlin/com/subtracks/ui/AppScreenshotTest.kt @@ -9,6 +9,7 @@ import androidx.activity.ComponentActivity import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule @@ -49,6 +50,7 @@ import com.subtracks.ui.playback.QueueScreen import com.subtracks.ui.settings.AddSourceScreen import com.subtracks.ui.settings.AddSourceState import com.subtracks.ui.settings.SettingsScreen +import com.subtracks.ui.theme.LocalPlayerArtwork import com.subtracks.ui.theme.SubtracksTheme import com.subtracks.ui.theme.artworkColorsFromSeed import com.subtracks.ui.theme.artworkColorsFromSeeds @@ -327,21 +329,23 @@ class AppScreenshotTest { private fun setLibraryContent(tab: LibraryTab) { composeRule.setContent { SubtracksTheme { - LibraryScreen( - selectedTab = tab, - onTabSelected = {}, - albums = remember { flowOf(PagingData.from(Fixtures.albums)) }.collectAsLazyPagingItems(), - artists = remember { flowOf(PagingData.from(Fixtures.artists)) }.collectAsLazyPagingItems(), - songs = remember { flowOf(PagingData.from(Fixtures.songItems)) }.collectAsLazyPagingItems(), - playlists = remember { flowOf(PagingData.from(Fixtures.playlists)) }.collectAsLazyPagingItems(), - coverArt = { id, _ -> id?.let { CoverArtRef(it, "test:$it") } }, - onAlbumClick = {}, - onArtistClick = {}, - onPlaylistClick = {}, - onSongClick = {}, - onSync = {}, - onOpenSettings = {}, - ) + CompositionLocalProvider(LocalPlayerArtwork provides artworkColorsFromSeed(Color.rgb(120, 80, 200))) { + LibraryScreen( + selectedTab = tab, + onTabSelected = {}, + albums = remember { flowOf(PagingData.from(Fixtures.albums)) }.collectAsLazyPagingItems(), + artists = remember { flowOf(PagingData.from(Fixtures.artists)) }.collectAsLazyPagingItems(), + songs = remember { flowOf(PagingData.from(Fixtures.songItems)) }.collectAsLazyPagingItems(), + playlists = remember { flowOf(PagingData.from(Fixtures.playlists)) }.collectAsLazyPagingItems(), + coverArt = { id, _ -> id?.let { CoverArtRef(it, "test:$it") } }, + onAlbumClick = {}, + onArtistClick = {}, + onPlaylistClick = {}, + onSongClick = {}, + onSync = {}, + onOpenSettings = {}, + ) + } } } }