diff --git a/app/src/main/java/org/listenbrainz/android/ui/components/BrainzPlayerListenCard.kt b/app/src/main/java/org/listenbrainz/android/ui/components/BrainzPlayerListenCard.kt deleted file mode 100644 index b7bc40e9..00000000 --- a/app/src/main/java/org/listenbrainz/android/ui/components/BrainzPlayerListenCard.kt +++ /dev/null @@ -1,152 +0,0 @@ -package org.listenbrainz.android.ui.components - -import androidx.annotation.DrawableRes -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.GenericShape -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.FilterQuality -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage -import coil.request.ImageRequest -import org.listenbrainz.android.R -import org.listenbrainz.android.model.feed.FeedListenArtist -import org.listenbrainz.android.ui.theme.ListenBrainzTheme - -@Composable -fun BrainzPlayerListenCard( - modifier: Modifier = Modifier, - title: String, - subTitle: String, - coverArtUrl: String?, - @DrawableRes errorAlbumArt: Int = R.drawable.ic_coverartarchive_logo_no_text, - onDropdownIconClick: () -> Unit = {}, - dropDown: @Composable () -> Unit = {}, - dropDownState: Boolean = false, - onPlayIconClick: () -> Unit -) { - Surface( - modifier = modifier - .fillMaxWidth(), - shape = ListenBrainzTheme.shapes.listenCardSmall, - shadowElevation = 4.dp, - color = ListenBrainzTheme.colorScheme.level1 - ) { - Column { - - Box( - modifier = Modifier - .fillMaxWidth() - .height(ListenBrainzTheme.sizes.listenCardHeight), - contentAlignment = Alignment.CenterStart - ) { - - Row( - modifier = Modifier.fillMaxWidth(0.7f), - verticalAlignment = Alignment.CenterVertically, - ) { - - AlbumArt(coverArtUrl, errorAlbumArt) - - Spacer(modifier = Modifier.width(ListenBrainzTheme.paddings.coverArtAndTextGap)) - - TitleAndSubtitle( - modifier = Modifier.padding(end = 6.dp), - title = title, - goToArtistPage = {}, - artists = listOf(FeedListenArtist(subTitle, null, "")), - ) - } - Box(modifier = Modifier - .fillMaxWidth(0.275f) - .align(Alignment.CenterEnd)){ - DropdownButton (modifier = Modifier.align(Alignment.Center), onDropdownIconClick = onDropdownIconClick) - if(dropDownState) dropDown() - PlayButton (modifier = Modifier.align(Alignment.CenterEnd)) { - onPlayIconClick() - } - } - - - - - - } - } - } -} - -@Composable -private fun DropdownButton(modifier: Modifier = Modifier, onDropdownIconClick: () -> Unit) { - - IconButton( - modifier = modifier, - onClick = onDropdownIconClick - ) { - Icon( - painter = painterResource(id = R.drawable.ic_options), - contentDescription = "", - tint = ListenBrainzTheme.colorScheme.hint, - modifier = Modifier.padding(horizontal = ListenBrainzTheme.paddings.insideCard) - ) - } -} - -@Composable -private fun PlayButton(modifier: Modifier = Modifier, onPlayIconClick: () -> Unit) { - - IconButton( - modifier = modifier, - onClick = onPlayIconClick - ) { - Icon( - painter = painterResource(id = R.drawable.brainz_player_play_button), - contentDescription = "", - tint = ListenBrainzTheme.colorScheme.hint, - modifier = Modifier.padding(horizontal = ListenBrainzTheme.paddings.insideCard) - ) - } -} - -@Composable -private fun AlbumArt( - coverArtUrl: String?, - errorAlbumArt: Int = R.drawable.ic_coverartarchive_logo_no_text -) { - // Use this for previews - AsyncImage( - model = ImageRequest.Builder(LocalContext.current) - .data(coverArtUrl) - .build(), - fallback = painterResource(id = errorAlbumArt), - error = painterResource(id = errorAlbumArt), - modifier = Modifier - .size(ListenBrainzTheme.sizes.listenCardHeight) - .clip(GenericShape { size, _ -> - addRect(Rect(0f, 0f, size.width*0.95f, size.height)) - }), - contentScale = ContentScale.Crop, - placeholder = painterResource(id = errorAlbumArt), - filterQuality = FilterQuality.Low, - contentDescription = "Album Cover Art" - ) -} - - diff --git a/app/src/main/java/org/listenbrainz/android/ui/components/ListenCardSmall.kt b/app/src/main/java/org/listenbrainz/android/ui/components/ListenCardSmall.kt index 98f3bedf..6bc21c9f 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/components/ListenCardSmall.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/components/ListenCardSmall.kt @@ -65,13 +65,17 @@ fun ListenCardSmall( coverArtUrl: String?, listenCount: Int? = null, @DrawableRes errorAlbumArt: Int = R.drawable.ic_coverartarchive_logo_no_text, - enableDropdownIcon: Boolean = false, onDropdownIconClick: () -> Unit = {}, - dropDown: @Composable () -> Unit = {}, + dropDown: @Composable (() -> Unit)? = null, enableTrailingContent: Boolean = false, trailingContent: @Composable (modifier: Modifier) -> Unit = {}, blurbContent: @Composable (ColumnScope.(modifier: Modifier) -> Unit)? = null, - color: Color = ListenBrainzTheme.colorScheme.level1, + isPlaying: Boolean = false, + color: Color = if (isPlaying) { + ListenBrainzTheme.colorScheme.level2 + } else { + ListenBrainzTheme.colorScheme.level1 + }, titleColor: Color = ListenBrainzTheme.colorScheme.listenText, subtitleColor: Color = titleColor.copy(alpha = 0.7f), goToArtistPage: (String) -> Unit, @@ -94,7 +98,8 @@ fun ListenCardSmall( contentAlignment = Alignment.CenterStart ) { - val (mainContentFraction, trailingContentFraction, dropDownButtonFraction) = remember(enableDropdownIcon, enableTrailingContent) { + val (mainContentFraction, trailingContentFraction, dropDownButtonFraction) = remember(dropDown != null, enableTrailingContent) { + val enableDropdownIcon = dropDown != null when { enableDropdownIcon && enableTrailingContent -> Triple(0.60f, 0.80f, 0.20f) // 0.20f (0.08f in whole) for dropdown and 0.80f (0.32f in whole) for trailing content enableDropdownIcon && !enableTrailingContent -> Triple(0.92f, 0f, 1f) // 0.10f for dropdown @@ -153,7 +158,7 @@ fun ListenCardSmall( } // Dropdown Icon - if (enableDropdownIcon) { + if (dropDown != null) { DropdownButton( modifier = Modifier .fillMaxWidth(dropDownButtonFraction) @@ -177,24 +182,68 @@ fun ListenCardSmall( } } -@Suppress("NOTHING_TO_INLINE") @Composable -inline fun ListenCardSmallDefault( +fun ListenCardSmall( + modifier: Modifier = Modifier, + trackName: String, + artist: String, + coverArtUrl: String?, + listenCount: Int? = null, + @DrawableRes errorAlbumArt: Int = R.drawable.ic_coverartarchive_logo_no_text, + onDropdownIconClick: () -> Unit = {}, + dropDown: @Composable () -> Unit = {}, + enableTrailingContent: Boolean = false, + trailingContent: @Composable (modifier: Modifier) -> Unit = {}, + blurbContent: @Composable (ColumnScope.(modifier: Modifier) -> Unit)? = null, + isPlaying: Boolean = false, + color: Color = if (isPlaying) { + ListenBrainzTheme.colorScheme.level2 + } else { + ListenBrainzTheme.colorScheme.level1 + }, + titleColor: Color = ListenBrainzTheme.colorScheme.listenText, + subtitleColor: Color = titleColor.copy(alpha = 0.7f), + goToArtistPage: (String) -> Unit, + onClick: () -> Unit, +) { + ListenCardSmall( + modifier = modifier, + trackName = trackName, + artists = listOf(FeedListenArtist(artist, null, "")), + coverArtUrl = coverArtUrl, + listenCount = listenCount, + errorAlbumArt = errorAlbumArt, + onDropdownIconClick = onDropdownIconClick, + dropDown = dropDown, + enableTrailingContent = enableTrailingContent, + trailingContent = trailingContent, + blurbContent = blurbContent, + isPlaying = isPlaying, + color = color, + titleColor = titleColor, + subtitleColor = subtitleColor, + goToArtistPage = goToArtistPage, + onClick = onClick + ) +} + +@Composable +fun ListenCardSmallDefault( modifier: Modifier = Modifier, metadata: Metadata, coverArtUrl: String?, listenCount: Int? = null, @DrawableRes errorAlbumArt: Int = R.drawable.ic_coverartarchive_logo_no_text, enableTrailingContent: Boolean = false, - noinline trailingContent: @Composable (modifier: Modifier) -> Unit = {}, - noinline blurbContent: @Composable (ColumnScope.(modifier: Modifier) -> Unit)? = null, + trailingContent: @Composable (modifier: Modifier) -> Unit = {}, + blurbContent: @Composable (ColumnScope.(modifier: Modifier) -> Unit)? = null, color: Color = ListenBrainzTheme.colorScheme.level1, titleColor: Color = ListenBrainzTheme.colorScheme.listenText, subtitleColor: Color = titleColor.copy(alpha = 0.7f), - noinline onDropdownError: suspend CoroutineScope.(error: ResponseError) -> Unit, - noinline onDropdownSuccess: suspend CoroutineScope.(message: String) -> Unit, - noinline goToArtistPage: (String) -> Unit, - noinline onClick: () -> Unit, + onDropdownError: suspend CoroutineScope.(error: ResponseError) -> Unit, + onDropdownSuccess: suspend CoroutineScope.(message: String) -> Unit, + goToArtistPage: (String) -> Unit, + onClick: () -> Unit, ) { metadata.trackMetadata?.let { var isDropdownExpanded by remember { mutableStateOf(false) } @@ -208,7 +257,6 @@ inline fun ListenCardSmallDefault( coverArtUrl = coverArtUrl, listenCount = listenCount, errorAlbumArt = errorAlbumArt, - enableDropdownIcon = true, onDropdownIconClick = { isDropdownExpanded = !isDropdownExpanded }, @@ -331,7 +379,6 @@ private fun ListenCardSmallPreview() { trackName = "Title", artists = listOf(FeedListenArtist("Artist", "", "")), coverArtUrl = "", - enableDropdownIcon = true, enableTrailingContent = true, trailingContent = { modifier -> Column(modifier = modifier) { @@ -357,7 +404,6 @@ private fun ListenCardSmallNoBlurbContentPreview() { trackName = "Title", artists = listOf(FeedListenArtist("Artist", "", "")), coverArtUrl = "", - enableDropdownIcon = true, enableTrailingContent = true, trailingContent = { modifier -> Column(modifier = modifier) { @@ -378,7 +424,6 @@ private fun ListenCardSmallSimplePreview() { trackName = "Title", artists = listOf(FeedListenArtist("Artist", "", "")), coverArtUrl = "", - enableDropdownIcon = true, enableTrailingContent = false, goToArtistPage = {}, ) {} diff --git a/app/src/main/java/org/listenbrainz/android/ui/navigation/BottomNavigationBar.kt b/app/src/main/java/org/listenbrainz/android/ui/navigation/BottomNavigationBar.kt index 9471bfcf..0b22f0b3 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/navigation/BottomNavigationBar.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/navigation/BottomNavigationBar.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview @@ -34,6 +35,7 @@ import org.listenbrainz.android.ui.theme.ListenBrainzTheme fun BottomNavigationBar( modifier: Modifier = Modifier, navController: NavController = rememberNavController(), + backgroundColor: Color = ListenBrainzTheme.colorScheme.nav, backdropScaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(initialValue = BackdropValue.Revealed), scrollToTop: () -> Unit, username : String?, @@ -46,7 +48,7 @@ fun BottomNavigationBar( ) BottomNavigation( modifier = modifier, - backgroundColor = ListenBrainzTheme.colorScheme.nav, + backgroundColor = backgroundColor, elevation = 0.dp ) { val coroutineScope = rememberCoroutineScope() diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/AlbumScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/AlbumScreen.kt index cb1fa5e0..17d31774 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/AlbumScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/AlbumScreen.kt @@ -290,7 +290,6 @@ fun OnAlbumClickScreen(albumID: Long) { artists = listOf(FeedListenArtist(it.artist, null, "")), coverArtUrl = it.albumArt, errorAlbumArt = R.drawable.ic_erroralbumart, - enableDropdownIcon = true, goToArtistPage = {}, onDropdownIconClick = { albumCardMoreOptionsDropMenuExpanded = albumSongs.indexOf(it) diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/ArtistScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/ArtistScreen.kt index 56408e76..91fd1e93 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/ArtistScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/ArtistScreen.kt @@ -376,7 +376,6 @@ fun OnArtistClickScreen(artistID: String, navigateToAlbum: (id: Long) -> Unit) { artists = listOf(FeedListenArtist(it.artist, null, "")), coverArtUrl = it.albumArt, errorAlbumArt = R.drawable.ic_erroralbumart, - enableDropdownIcon = true, onDropdownIconClick = { artistCardMoreOptionsDropMenuExpanded = artistSongs.indexOf(it) }, diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt index af97b4ad..b607e335 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.material.Checkbox import androidx.compose.material.CheckboxDefaults import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.Icon -import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.RepeatOn @@ -60,7 +59,6 @@ import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerScreen.kt index 03716d8b..ac5ce6b4 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -54,43 +55,58 @@ fun BrainzPlayerScreen() { val BPArtistViewModel = hiltViewModel() val playlistViewModel = hiltViewModel() val brainzPlayerViewModel = hiltViewModel() - + // Data streams - val albums = BPAlbumViewModel.albums.collectAsState(initial = listOf()).value // TODO: Introduce initial values to avoid flicker. + val albums = + BPAlbumViewModel.albums.collectAsState(initial = listOf()).value // TODO: Introduce initial values to avoid flicker. val songs = songsViewModel.songs.collectAsState(initial = listOf()).value val artists = BPArtistViewModel.artists.collectAsState(initial = listOf()).value val playlists by playlistViewModel.playlists.collectAsState(initial = listOf()) - val songsPlayedToday = brainzPlayerViewModel.songsPlayedToday.collectAsState(initial = listOf()).value - val recentlyPlayed = brainzPlayerViewModel.recentlyPlayed.collectAsState(initial = mutableListOf()).value + val songsPlayedToday = + brainzPlayerViewModel.songsPlayedToday.collectAsState(initial = listOf()).value + val recentlyPlayed = + brainzPlayerViewModel.recentlyPlayed.collectAsState(initial = mutableListOf()).value val topRecents = recentlyPlayed.take(5).toMutableList() val topArtists = artists.take(5).toMutableList() val topAlbums = albums.take(5).toMutableList() - val albumSongsMap : MutableMap> = mutableMapOf() + val albumSongsMap: MutableMap> = mutableMapOf() - for(i in 1..albums.size){ - val albumSongs : List = BPAlbumViewModel.getAllSongsOfAlbum(albums[i-1].albumId).collectAsState( - initial = listOf() - ).value - albumSongsMap[albums[i-1]] = albumSongs + for (i in 1..albums.size) { + val albumSongs: List = + BPAlbumViewModel.getAllSongsOfAlbum(albums[i - 1].albumId).collectAsState( + initial = listOf() + ).value + albumSongsMap[albums[i - 1]] = albumSongs } - val songsPlayedThisWeek = brainzPlayerViewModel.songsPlayedThisWeek.collectAsState(initial = listOf()).value + val songsPlayedThisWeek = + brainzPlayerViewModel.songsPlayedThisWeek.collectAsState(initial = listOf()).value topRecents.add(Song()) topArtists.add(Artist()) topAlbums.add(Album()) - + Column( modifier = Modifier.fillMaxSize() ) { - Navigation(albums = albums, previewAlbums = topAlbums, artists = artists, previewArtists = topArtists, playlists, songsPlayedToday, songsPlayedThisWeek ,topRecents ,songs, albumSongsMap) + Navigation( + albums = albums, + previewAlbums = topAlbums, + artists = artists, + previewArtists = topArtists, + playlists, + songsPlayedToday, + songsPlayedThisWeek, + topRecents, + songs, + albumSongsMap + ) } } -@RequiresApi(Build.VERSION_CODES.O) @Composable fun BrainzPlayerHomeScreen( - songs : List, + songs: List, albums: List, previewAlbums: List, artists: List, @@ -98,27 +114,24 @@ fun BrainzPlayerHomeScreen( songsPlayedToday: List, songsPlayedThisWeek: List, recentlyPlayedSongs: List, - albumSongsMap: MutableMap>, + albumSongsMap: MutableMap>, brainzPlayerViewModel: BrainzPlayerViewModel = hiltViewModel(), ) { + val currentTab = remember { mutableIntStateOf(0) } - val currentTab : MutableState = remember {mutableStateOf(0)} - val currentlyPlayingSong = - brainzPlayerViewModel.currentlyPlayingSong.collectAsState().value.toSong - val isPlaying = brainzPlayerViewModel.isPlaying Column { Row( modifier = Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()) - .background( - Brush.verticalGradient( - listOf( - ListenBrainzTheme.colorScheme.background, - Color.Transparent + .fillMaxWidth() + .horizontalScroll(rememberScrollState()) + .background( + Brush.verticalGradient( + listOf( + ListenBrainzTheme.colorScheme.background, + Color.Transparent + ) ) ) - ) ) { Spacer(modifier = Modifier.width(ListenBrainzTheme.paddings.chipsHorizontal / 2)) repeat(5) { position -> @@ -147,26 +160,27 @@ fun BrainzPlayerHomeScreen( color = ListenBrainzTheme.colorScheme.text, ) }, - onClick = {currentTab.value = position} + onClick = { currentTab.value = position } ) } } + when (currentTab.value) { 0 -> OverviewScreen( songsPlayedToday = songsPlayedToday, recentlyPlayedSongs = recentlyPlayedSongs, - goToRecentScreen = {currentTab.value = 1}, - goToArtistScreen = {currentTab.value = 2}, - goToAlbumScreen = {currentTab.value = 3}, + goToRecentScreen = { currentTab.value = 1 }, + goToArtistScreen = { currentTab.value = 2 }, + goToAlbumScreen = { currentTab.value = 3 }, brainzPlayerViewModel = brainzPlayerViewModel, artists = previewArtists, albums = previewAlbums ) + 1 -> RecentPlaysScreen( songsPlayedToday = songsPlayedToday, songsPlayedThisWeek = songsPlayedThisWeek, - onPlayIconClick = { - song -> + onPlayIconClick = { song -> brainzPlayerViewModel.changePlayable( listOf(song), PlayableType.ALL_SONGS, @@ -174,72 +188,23 @@ fun BrainzPlayerHomeScreen( 0, 0L ) - brainzPlayerViewModel.playOrToggleSong(song,true) + brainzPlayerViewModel.playOrToggleSong(song, true) }, - onAddToQueue = { - song -> - val currentSongs = brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.toMutableList() - currentSongs?.add(currentSongs.size, song) - brainzPlayerViewModel.appPreferences.currentPlayable = brainzPlayerViewModel.appPreferences.currentPlayable?.copy(songs = currentSongs ?: emptyList()) - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.let { - brainzPlayerViewModel.changePlayable( - it, - PlayableType.ALL_SONGS, - brainzPlayerViewModel.appPreferences.currentPlayable?.id ?: 0, - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } ?: 0,brainzPlayerViewModel.songCurrentPosition.value - ) - } - brainzPlayerViewModel.queueChanged( - currentlyPlayingSong, - brainzPlayerViewModel.isPlaying.value - ) + onAddToQueue = { song -> + brainzPlayerViewModel.addToQueue(listOf(song)) }, - onPlayNext = { - song -> - val currentSongIndex = - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } - ?.plus(1) - if (isPlaying.value && currentSongIndex != null) { - val currentSongs = brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.toMutableList() - currentSongs?.add(currentSongIndex, song) - brainzPlayerViewModel.appPreferences.currentPlayable = brainzPlayerViewModel.appPreferences.currentPlayable?.copy(songs = currentSongs ?: emptyList()) - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.let { - brainzPlayerViewModel.changePlayable( - it, - PlayableType.ALL_SONGS, - brainzPlayerViewModel.appPreferences.currentPlayable?.id ?: 0, - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } ?: 0,brainzPlayerViewModel.songCurrentPosition.value - ) - } - brainzPlayerViewModel.queueChanged( - currentlyPlayingSong, - brainzPlayerViewModel.isPlaying.value - ) - } - else{ - // No song is playing, so start playing the selected song - brainzPlayerViewModel.changePlayable( - listOf(song), - PlayableType.SONG, - song.mediaID, - 0, - 0L - ) - brainzPlayerViewModel.playOrToggleSong(song, true) - } - + onPlayNext = { song -> + brainzPlayerViewModel.playNext(listOf(song)) }, - onAddToExistingPlaylist = { - song -> + onAddToExistingPlaylist = { song -> }, - onAddToNewPlaylist = { - song -> + onAddToNewPlaylist = { song -> } ) + 2 -> ArtistsOverviewScreen( artists = artists, - onPlayClick = { - artist -> + onPlayClick = { artist -> brainzPlayerViewModel.changePlayable( artist.songs, PlayableType.ARTIST, @@ -249,66 +214,19 @@ fun BrainzPlayerHomeScreen( ) brainzPlayerViewModel.playOrToggleSong(artist.songs[0], true) }, - onPlayNext = { - artist -> - val currentSongIndex = - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } - ?.plus(1) - if (isPlaying.value && currentSongIndex != null) { - val currentSongs = brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.toMutableList() - currentSongs?.addAll(currentSongIndex, artist.songs) - brainzPlayerViewModel.appPreferences.currentPlayable = brainzPlayerViewModel.appPreferences.currentPlayable?.copy(songs = currentSongs ?: emptyList()) - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.let { - brainzPlayerViewModel.changePlayable( - it, - PlayableType.ALL_SONGS, - brainzPlayerViewModel.appPreferences.currentPlayable?.id ?: 0, - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } ?: 0,brainzPlayerViewModel.songCurrentPosition.value - ) - } - brainzPlayerViewModel.queueChanged( - currentlyPlayingSong, - brainzPlayerViewModel.isPlaying.value - ) - } - else{ - brainzPlayerViewModel.changePlayable( - artist.songs, - PlayableType.ARTIST, - artist.id, - 0, - 0L - ) - brainzPlayerViewModel.playOrToggleSong(artist.songs[0], true) - } + onPlayNext = { artist -> + brainzPlayerViewModel.playNext(artist.songs) }, - onAddToQueue = { - artist -> - val currentSongs = brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.toMutableList() - currentSongs?.addAll(currentSongs.size, artist.songs) - brainzPlayerViewModel.appPreferences.currentPlayable = brainzPlayerViewModel.appPreferences.currentPlayable?.copy(songs = currentSongs ?: emptyList()) - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.let { - brainzPlayerViewModel.changePlayable( - it, - PlayableType.ALL_SONGS, - brainzPlayerViewModel.appPreferences.currentPlayable?.id ?: 0, - brainzPlayerViewModel.appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID==currentlyPlayingSong.mediaID } ?: 0,brainzPlayerViewModel.songCurrentPosition.value - ) - } - brainzPlayerViewModel.queueChanged( - currentlyPlayingSong, - brainzPlayerViewModel.isPlaying.value - ) + onAddToQueue = { artist -> + brainzPlayerViewModel.addToQueue(artist.songs) }, - onAddToNewPlaylist = { - artist -> + onAddToNewPlaylist = { artist -> }, - onAddToExistingPlaylist = { - artist -> + onAddToExistingPlaylist = { artist -> } ) - 3 -> AlbumsOverViewScreen(albums = albums, onPlayIconClick = { - album -> + + 3 -> AlbumsOverViewScreen(albums = albums, onPlayIconClick = { album -> val albumSongs = albumSongsMap[album]!! brainzPlayerViewModel.changePlayable( albumSongs.sortedBy { it.trackNumber }, @@ -316,24 +234,37 @@ fun BrainzPlayerHomeScreen( album.albumId, albumSongs .sortedBy { it.trackNumber } - .indexOf (albumSongs[0]), + .indexOf(albumSongs[0]), 0L ) - brainzPlayerViewModel.playOrToggleSong(albumSongs[0],true) + brainzPlayerViewModel.playOrToggleSong(albumSongs[0], true) }) - 4 -> SongsOverviewScreen(songs = songs, onPlayIconClick = { - song , newPlayables -> - brainzPlayerViewModel.changePlayable( - newPlayables, - PlayableType.ALL_SONGS, - song.mediaID, - newPlayables.sortedBy { it.discNumber }.indexOf(song), - 0L - ) - brainzPlayerViewModel.playOrToggleSong(song,true) - }) + + 4 -> SongsOverviewScreen( + songs = songs, + onPlayIconClick = { song, newPlayables -> + brainzPlayerViewModel.changePlayable( + newPlayables, + PlayableType.ALL_SONGS, + song.mediaID, + newPlayables.sortedBy { it.discNumber }.indexOf(song), + 0L + ) + brainzPlayerViewModel.playOrToggleSong(song, true) + }, + onAddToQueue = { song -> + brainzPlayerViewModel.addToQueue(listOf(song)) + }, + onPlayNext = { song -> + brainzPlayerViewModel.playNext(listOf(song)) + }, + onAddToExistingPlaylist = { song -> + }, + onAddToNewPlaylist = { song -> + } + ) } } } \ No newline at end of file diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/PlaylistScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/PlaylistScreen.kt index 7073f5c2..3dea5469 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/PlaylistScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/PlaylistScreen.kt @@ -415,7 +415,6 @@ fun OnPlaylistClickScreen(playlistID: Long) { artists = listOf(FeedListenArtist(it.artist, null, "")), coverArtUrl = it.albumArt, errorAlbumArt = R.drawable.ic_erroralbumart, - enableDropdownIcon = true, goToArtistPage = {}, onDropdownIconClick = { selectedPlaylistItemIndex = selectedPlaylist.items.indexOf(it) diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/navigation/BrainzPlayerNavigation.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/navigation/BrainzPlayerNavigation.kt index 64e5e906..a9a24527 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/navigation/BrainzPlayerNavigation.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/navigation/BrainzPlayerNavigation.kt @@ -25,7 +25,6 @@ import org.listenbrainz.android.ui.screens.brainzplayer.PlaylistScreen import org.listenbrainz.android.ui.screens.brainzplayer.SongScreen -@RequiresApi(Build.VERSION_CODES.O) @ExperimentalMaterial3Api @Composable fun Navigation( @@ -41,9 +40,6 @@ fun Navigation( albumSongsMap: MutableMap>, navHostController: NavHostController = rememberNavController() ) { - - fun goTo(destination: BrainzPlayerNavigationItem) = navHostController.navigate(destination.route) - NavHost(navController = navHostController, startDestination = BrainzPlayerNavigationItem.Home.route) { composable(route = BrainzPlayerNavigationItem.Home.route) { diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/AlbumsOverviewScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/AlbumsOverviewScreen.kt index 977a3a9e..fbfa87f2 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/AlbumsOverviewScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/AlbumsOverviewScreen.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.listenbrainz.android.R import org.listenbrainz.android.model.Album -import org.listenbrainz.android.ui.components.BrainzPlayerListenCard +import org.listenbrainz.android.ui.components.ListenCardSmall import org.listenbrainz.android.ui.theme.ListenBrainzTheme @Composable @@ -54,14 +54,21 @@ fun AlbumsOverViewScreen( ) for (j in 1..albumsStarting[startingLetter]!!.size) { val coverArt = albumsStarting[startingLetter]!![j - 1].albumArt - BrainzPlayerListenCard(title = albumsStarting[startingLetter]!![j - 1].title, subTitle = albumsStarting[startingLetter]!![j - 1].artist, coverArtUrl = coverArt, errorAlbumArt = R.drawable.ic_erroralbumart, modifier = Modifier.padding( - start = 10.dp, - end = 10.dp, - top = 3.dp, - bottom = 3.dp - ), onPlayIconClick = { - onPlayIconClick(albumsStarting[startingLetter]!![j-1]) - }) + ListenCardSmall( + trackName = albumsStarting[startingLetter]!![j - 1].title, + artist = albumsStarting[startingLetter]!![j - 1].artist, + coverArtUrl = coverArt, + errorAlbumArt = R.drawable.ic_erroralbumart, + modifier = Modifier.padding( + start = 10.dp, + end = 10.dp, + top = 3.dp, + bottom = 3.dp + ), + goToArtistPage = { onPlayIconClick(albumsStarting[startingLetter]!![j-1]) }, + onClick = { onPlayIconClick(albumsStarting[startingLetter]!![j-1]) } + ) + Spacer(modifier = Modifier.height(10.dp)) } } diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/ArtistsOverviewScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/ArtistsOverviewScreen.kt index 3a886e6b..0f7c8ad0 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/ArtistsOverviewScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/ArtistsOverviewScreen.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.sp import org.listenbrainz.android.R import org.listenbrainz.android.model.Artist import org.listenbrainz.android.ui.components.BrainzPlayerDropDownMenu -import org.listenbrainz.android.ui.components.BrainzPlayerListenCard +import org.listenbrainz.android.ui.components.ListenCardSmall import org.listenbrainz.android.ui.theme.ListenBrainzTheme @Composable @@ -71,12 +71,31 @@ fun ArtistsOverviewScreen( val artist = artistsStarting[startingLetter]!![j-1] if (artistsStarting[startingLetter]!![j - 1].albums.isNotEmpty()) coverArt = artistsStarting[startingLetter]!![j - 1].albums[0].albumArt - BrainzPlayerListenCard(title = artistsStarting[startingLetter]!![j - 1].name, subTitle = when (artistsStarting[startingLetter]!![j - 1].songs.size) { - 1 -> "1 track" - else -> "${artistsStarting[startingLetter]!![j - 1].songs.size} tracks" - }, coverArtUrl = coverArt, errorAlbumArt = R.drawable.ic_artist, onPlayIconClick = { - onPlayClick(artistsStarting[startingLetter]!![j-1]) - }, modifier = Modifier.padding(start = 10.dp, end = 10.dp), dropDown = { BrainzPlayerDropDownMenu(onAddToNewPlaylist = {onAddToNewPlaylist(artist)}, onAddToExistingPlaylist = {onAddToExistingPlaylist(artist)},onAddToQueue = {onAddToQueue(artist)}, onPlayNext = {onPlayNext(artist)},expanded = dropdownState == Pair(i,j-1), onDismiss = {dropdownState = Pair(-1,-1)})}, onDropdownIconClick = {dropdownState = Pair(i,j-1)}, dropDownState = dropdownState == Pair(i,j-1)) + ListenCardSmall( + trackName = artistsStarting[startingLetter]!![j - 1].name, + artist = when (artistsStarting[startingLetter]!![j - 1].songs.size) { + 1 -> "1 track" + else -> "${artistsStarting[startingLetter]!![j - 1].songs.size} tracks" + }, + coverArtUrl = coverArt, + errorAlbumArt = R.drawable.ic_artist, + modifier = Modifier.padding(start = 10.dp, end = 10.dp), + dropDown = { + BrainzPlayerDropDownMenu( + onAddToNewPlaylist = {onAddToNewPlaylist(artist)}, + onAddToExistingPlaylist = {onAddToExistingPlaylist(artist)}, + onAddToQueue = {onAddToQueue(artist)}, + onPlayNext = {onPlayNext(artist)}, + expanded = dropdownState == Pair(i,j-1), + onDismiss = {dropdownState = Pair(-1,-1)} + ) + }, + onDropdownIconClick = { dropdownState = Pair(i,j-1) }, + goToArtistPage = {}, + onClick = { + onPlayClick(artistsStarting[startingLetter]!![j-1]) + }, + ) Spacer(modifier = Modifier.height(10.dp)) } } diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/RecentPlaysOverviewScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/RecentPlaysOverviewScreen.kt index 593e0478..398fa474 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/RecentPlaysOverviewScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/RecentPlaysOverviewScreen.kt @@ -1,6 +1,7 @@ package org.listenbrainz.android.ui.screens.brainzplayer.overview import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -18,11 +19,15 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.listenbrainz.android.R import org.listenbrainz.android.model.Song import org.listenbrainz.android.ui.components.BrainzPlayerDropDownMenu -import org.listenbrainz.android.ui.components.BrainzPlayerListenCard +import org.listenbrainz.android.ui.components.ListenCardSmall import org.listenbrainz.android.ui.theme.ListenBrainzTheme +import org.listenbrainz.android.util.BrainzPlayerExtensions.toSong +import org.listenbrainz.android.viewmodel.BrainzPlayerViewModel @Composable fun RecentPlaysScreen( @@ -43,14 +48,14 @@ fun RecentPlaysScreen( .background( brush = ListenBrainzTheme.colorScheme.gradientBrush ) - .padding(top = 15.dp, bottom = 15.dp, start = 10.dp)) { + .padding(top = 15.dp, bottom = 15.dp, start = 10.dp, end = 10.dp)) { Text( "Played Today", color = ListenBrainzTheme.colorScheme.lbSignature, fontSize = 25.sp ) Spacer(modifier = Modifier.height(10.dp)) - PlayedToday(songsPlayedToday = songsPlayedToday, onPlayIconClick = onPlayIconClick, dropDownState = dropdownState, onAddToQueue = onAddToQueue, onAddToNewPlaylist = onAddToNewPlaylist, onAddToExistingPlaylist = onAddToExistingPlaylist, onPlayNext = onPlayNext) + PlayedThisWeek(songsPlayed = songsPlayedToday, onPlayIconClick = onPlayIconClick, dropDownState = dropdownState, onAddToQueue = onAddToQueue, onAddToNewPlaylist = onAddToNewPlaylist, onAddToExistingPlaylist = onAddToExistingPlaylist, onPlayNext = onPlayNext) } } if(songsPlayedThisWeek.isNotEmpty()) { @@ -58,52 +63,23 @@ fun RecentPlaysScreen( .background( brush = ListenBrainzTheme.colorScheme.gradientBrush ) - .padding(top = 15.dp, bottom = 15.dp, start = 10.dp)) { + .padding(top = 15.dp, bottom = 15.dp, start = 10.dp, end = 10.dp)) { Text( "Played This Week", color = ListenBrainzTheme.colorScheme.lbSignature, fontSize = 25.sp ) Spacer(modifier = Modifier.height(10.dp)) - PlayedThisWeek(songsPlayedThisWeek = songsPlayedThisWeek, onPlayIconClick = onPlayIconClick, dropDownState = dropdownState, onAddToQueue = onAddToQueue, onAddToNewPlaylist = onAddToNewPlaylist, onAddToExistingPlaylist = onAddToExistingPlaylist, onPlayNext = onPlayNext) + PlayedThisWeek(songsPlayed = songsPlayedThisWeek, onPlayIconClick = onPlayIconClick, dropDownState = dropdownState, onAddToQueue = onAddToQueue, onAddToNewPlaylist = onAddToNewPlaylist, onAddToExistingPlaylist = onAddToExistingPlaylist, onPlayNext = onPlayNext) } } } } -@Composable -private fun PlayedToday( - songsPlayedToday: List, - onPlayIconClick: (Song) -> Unit, - dropDownState : MutableState>, - onAddToQueue: (Song) -> Unit, - onPlayNext: (Song) -> Unit, - onAddToExistingPlaylist: (Song) -> Unit, - onAddToNewPlaylist: (Song) -> Unit -){ - var heightConstraint = ListenBrainzTheme.sizes.listenCardHeight * songsPlayedToday.size + 20.dp - if(songsPlayedToday.size > 4) heightConstraint = 250.dp - LazyColumn (modifier = Modifier.height( - heightConstraint - )) { - itemsIndexed(songsPlayedToday){ - index, it -> - BrainzPlayerListenCard(title = it.title, subTitle = it.artist, coverArtUrl = it.albumArt, errorAlbumArt = R.drawable.ic_erroralbumart, onPlayIconClick = {onPlayIconClick(it)}, onDropdownIconClick = {dropDownState.value = Pair(1,index)}, dropDownState = dropDownState.value == Pair(1,index),dropDown = {BrainzPlayerDropDownMenu( - expanded = dropDownState.value == Pair(1,index), - onDismiss = {dropDownState.value = Pair(-1,-1)}, - onAddToQueue = {onAddToQueue(it)}, - onPlayNext = {onPlayNext(it)}, - onAddToExistingPlaylist = {onAddToExistingPlaylist(it)}, - onAddToNewPlaylist = {onAddToNewPlaylist(it)} - )}) - Spacer(modifier = Modifier.height(5.dp)) - } - } -} @Composable private fun PlayedThisWeek( - songsPlayedThisWeek: List, + songsPlayed: List, onPlayIconClick: (Song) -> Unit, dropDownState : MutableState>, onAddToQueue: (Song) -> Unit, @@ -111,22 +87,36 @@ private fun PlayedThisWeek( onAddToExistingPlaylist: (Song) -> Unit, onAddToNewPlaylist: (Song) -> Unit ){ - var heightConstraint = ListenBrainzTheme.sizes.listenCardHeight * songsPlayedThisWeek.size + 20.dp - if(songsPlayedThisWeek.size > 4) heightConstraint = 250.dp - LazyColumn (modifier = Modifier.height( - heightConstraint - )) { - itemsIndexed(songsPlayedThisWeek){ - index, it -> - BrainzPlayerListenCard(title = it.title, subTitle = it.artist, coverArtUrl = it.albumArt, errorAlbumArt = R.drawable.ic_erroralbumart, onPlayIconClick = {onPlayIconClick(it)}, onDropdownIconClick = {dropDownState.value = Pair(2,index)}, dropDownState = dropDownState.value == Pair(2,index),dropDown = {BrainzPlayerDropDownMenu( - expanded = dropDownState.value == Pair(2,index), - onDismiss = {dropDownState.value = Pair(-1,-1)}, - onAddToQueue = {onAddToQueue(it)}, - onPlayNext = {onPlayNext(it)}, - onAddToExistingPlaylist = {onAddToExistingPlaylist(it)}, - onAddToNewPlaylist = {onAddToNewPlaylist(it)} - )}) - Spacer(modifier = Modifier.height(5.dp)) + val viewModel: BrainzPlayerViewModel = hiltViewModel() + val currentlyPlayingSong = viewModel.currentlyPlayingSong.collectAsStateWithLifecycle().value.toSong + var heightConstraint = ListenBrainzTheme.sizes.listenCardHeight * songsPlayed.size + 20.dp + if (songsPlayed.size > 4) + heightConstraint = 250.dp + LazyColumn ( + modifier = Modifier.height(heightConstraint), + verticalArrangement = Arrangement.spacedBy(ListenBrainzTheme.paddings.lazyListAdjacent) + ) { + itemsIndexed(songsPlayed){ index, it -> + ListenCardSmall( + trackName = it.title, + artist = it.artist, + coverArtUrl = it.albumArt, + errorAlbumArt = R.drawable.ic_erroralbumart, + onClick = { onPlayIconClick(it) }, + goToArtistPage = {}, + onDropdownIconClick = { dropDownState.value = Pair(2,index) }, + dropDown = { + BrainzPlayerDropDownMenu( + expanded = dropDownState.value == Pair(2,index), + onDismiss = {dropDownState.value = Pair(-1,-1)}, + onAddToQueue = {onAddToQueue(it)}, + onPlayNext = {onPlayNext(it)}, + onAddToExistingPlaylist = {onAddToExistingPlaylist(it)}, + onAddToNewPlaylist = {onAddToNewPlaylist(it)} + ) + }, + isPlaying = it.mediaID == currentlyPlayingSong.mediaID + ) } } } \ No newline at end of file diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/SongsOverviewScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/SongsOverviewScreen.kt index 845357a6..9e1141fb 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/SongsOverviewScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/overview/SongsOverviewScreen.kt @@ -9,35 +9,55 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.listenbrainz.android.R +import org.listenbrainz.android.model.Artist import org.listenbrainz.android.model.Song -import org.listenbrainz.android.ui.components.BrainzPlayerListenCard +import org.listenbrainz.android.ui.components.BrainzPlayerDropDownMenu +import org.listenbrainz.android.ui.components.ListenCardSmall import org.listenbrainz.android.ui.theme.ListenBrainzTheme +import org.listenbrainz.android.util.BrainzPlayerExtensions.toSong +import org.listenbrainz.android.viewmodel.BrainzPlayerViewModel @Composable fun SongsOverviewScreen( songs: List, onPlayIconClick: (Song, List) -> Unit, + onPlayNext : (Song) -> Unit, + onAddToQueue : (Song) -> Unit, + onAddToExistingPlaylist : (Song) -> Unit, + onAddToNewPlaylist : (Song) -> Unit, ) { - val songsStarting : MutableMap> = mutableMapOf() - for (i in 0..25) { - songsStarting['A' + i] = mutableListOf() - } + val songsStarting = remember(songs.size) { + val songsStarting = mutableMapOf>() + for (i in 0..25) { + songsStarting['A' + i] = mutableListOf() + } - for (i in 1..songs.size) { - songsStarting[songs[i - 1].title[0]]?.add(songs[i-1]) + for (i in 1..songs.size) { + songsStarting[songs[i - 1].title[0]]?.add(songs[i-1]) + } + songsStarting } + val viewModel: BrainzPlayerViewModel = hiltViewModel() + val currentlyPlayingSong = viewModel.currentlyPlayingSong.collectAsStateWithLifecycle().value.toSong + Column(modifier = Modifier.verticalScroll(rememberScrollState())) { for (i in 0..25) { - val startingLetter: Char = ('A' + i) - if (songsStarting[startingLetter]!!.size > 0) { + val startingLetter = ('A' + i) + if (songsStarting[startingLetter]!!.isNotEmpty()) { Column( modifier = Modifier.background( brush = ListenBrainzTheme.colorScheme.gradientBrush @@ -53,12 +73,34 @@ fun SongsOverviewScreen( ) ) for (j in 1..songsStarting[startingLetter]!!.size) { - val song: Song = songsStarting[startingLetter]!![j-1] - var coverArt: String? = null - coverArt = songsStarting[startingLetter]!![j - 1].albumArt - BrainzPlayerListenCard(modifier = Modifier.padding(start= 10.dp, end = 10.dp),title = songsStarting[startingLetter]!![j - 1].title, subTitle = songsStarting[startingLetter]!![j - 1].artist, coverArtUrl = coverArt, errorAlbumArt = R.drawable.ic_erroralbumart){ - onPlayIconClick(song,songsStarting[startingLetter]!!) - } + val song = songsStarting[startingLetter]!![j-1] + val coverArt = songsStarting[startingLetter]!![j - 1].albumArt + + var showDropdown by remember { mutableStateOf(false) } + + ListenCardSmall( + modifier = Modifier.padding(start = 10.dp, end = 10.dp), + trackName = songsStarting[startingLetter]!![j - 1].title, + artist = songsStarting[startingLetter]!![j - 1].artist, + coverArtUrl = coverArt, + errorAlbumArt = R.drawable.ic_erroralbumart, + onClick = { onPlayIconClick(song, songsStarting[startingLetter]!!) }, + onDropdownIconClick = { + showDropdown = !showDropdown + }, + goToArtistPage = { }, + isPlaying = song.mediaID == currentlyPlayingSong.mediaID, + dropDown = { + BrainzPlayerDropDownMenu( + onAddToNewPlaylist = {onAddToNewPlaylist(song)}, + onAddToExistingPlaylist = {onAddToExistingPlaylist(song)}, + onAddToQueue = {onAddToQueue(song)}, + onPlayNext = {onPlayNext(song)}, + expanded = showDropdown, + onDismiss = { showDropdown = false }, + ) + } + ) Spacer(modifier = Modifier.height(10.dp)) } } diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt index 047a2105..ee35a899 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt @@ -526,7 +526,6 @@ fun FollowListens( caaReleaseMbid = event.metadata.trackMetadata?.mbidMapping?.caaReleaseMbid, caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ), - enableDropdownIcon = true, onDropdownIconClick = { dropdownItemIndex.value = if (dropdownItemIndex.value == null) index else null }, @@ -630,7 +629,6 @@ fun SimilarListens( caaReleaseMbid = event.metadata.trackMetadata?.mbidMapping?.caaReleaseMbid, caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ), - enableDropdownIcon = true, onDropdownIconClick = { dropdownItemIndex.value = if (dropdownItemIndex.value == null){ index diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenFeedLayout.kt index b137a155..e26a4efd 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenFeedLayout.kt @@ -49,7 +49,6 @@ fun ListenFeedLayout ( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenLikeFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenLikeFeedLayout.kt index d64682f6..71d6d3e2 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenLikeFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ListenLikeFeedLayout.kt @@ -48,7 +48,6 @@ fun ListenLikeFeedLayout( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PersonalRecommendationFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PersonalRecommendationFeedLayout.kt index 416b5b3a..416611b9 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PersonalRecommendationFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PersonalRecommendationFeedLayout.kt @@ -60,7 +60,6 @@ fun PersonalRecommendationFeedLayout( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PinFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PinFeedLayout.kt index e4183311..ebd29cc8 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PinFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/PinFeedLayout.kt @@ -52,7 +52,6 @@ fun PinFeedLayout( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( @@ -80,7 +79,6 @@ fun PinFeedLayout( goToArtistPage = goToArtistPage, onClick = onClick ) - } } diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/RecordingRecommendationFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/RecordingRecommendationFeedLayout.kt index ee130766..9d875401 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/RecordingRecommendationFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/RecordingRecommendationFeedLayout.kt @@ -48,7 +48,6 @@ fun RecordingRecommendationFeedLayout( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ReviewFeedLayout.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ReviewFeedLayout.kt index 541636f4..6298a422 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ReviewFeedLayout.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/events/ReviewFeedLayout.kt @@ -71,7 +71,6 @@ fun ReviewFeedLayout( caaId = event.metadata.trackMetadata?.mbidMapping?.caaId ) }, - enableDropdownIcon = true, onDropdownIconClick = onDropdownClick, dropDown = { SocialDropdown( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/stats/StatsScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/stats/StatsScreen.kt index 025d8463..9b0e4ab9 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/stats/StatsScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/stats/StatsScreen.kt @@ -5,7 +5,6 @@ import android.text.TextUtils import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -63,7 +62,6 @@ import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.listenbrainz.android.R -import org.listenbrainz.android.model.Listen import org.listenbrainz.android.model.Metadata import org.listenbrainz.android.model.SocialUiState import org.listenbrainz.android.model.TrackMetadata @@ -477,7 +475,6 @@ fun StatsScreen( subtitleColor = ListenBrainzTheme.colorScheme.listenText.copy(alpha = 0.7f), enableTrailingContent = true, listenCount = topAlbum.listenCount, - enableDropdownIcon = true, goToArtistPage = goToArtistPage ) { @@ -512,7 +509,6 @@ fun StatsScreen( color = app_bg_secondary_dark, titleColor = ListenBrainzTheme.colorScheme.followerChipSelected, subtitleColor = ListenBrainzTheme.colorScheme.listenText.copy(alpha = 0.7f), - enableDropdownIcon = true, onDropdownIconClick = { dropdownItemIndex.value = index }, diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/taste/TasteScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/taste/TasteScreen.kt index 8eb0647b..566a4421 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/taste/TasteScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/taste/TasteScreen.kt @@ -189,7 +189,6 @@ fun TasteScreen( caaReleaseMbid = feedback.trackMetadata?.mbidMapping?.caaReleaseMbid, caaId = feedback.trackMetadata?.mbidMapping?.caaId ), - enableDropdownIcon = true, onDropdownIconClick = { dropdownItemIndex.value = index }, @@ -286,7 +285,6 @@ fun TasteScreen( caaReleaseMbid = recording.trackMetadata?.mbidMapping?.caaReleaseMbid, caaId = recording.trackMetadata?.mbidMapping?.caaId ), - enableDropdownIcon = true, onDropdownIconClick = { dropdownItemIndex.value = index }, diff --git a/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt b/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt index 99304e23..0613f1e7 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt @@ -1,6 +1,5 @@ package org.listenbrainz.android.ui.theme -import android.app.Activity import android.content.Context import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.isSystemInDarkTheme @@ -22,7 +21,6 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.TextStyle @@ -108,7 +106,7 @@ private val colorSchemeDark = ColorScheme( onBackground = Color.White, nav = bp_bottom_song_viewpager_dark, level1 = app_bottom_nav_dark, - level2 = Color(0xFF4E4E4E), + level2 = Color(0xFF3B3B3B), lbSignature = Color(0xFF9AABD1), lbSignatureSecondary = lb_yellow, lbSignatureInverse = lb_orange, @@ -146,7 +144,7 @@ private val colorSchemeLight = ColorScheme( onBackground = Color.Black, nav = bp_bottom_song_viewpager_day, level1 = app_bottom_nav_day, - level2 = Color(0xFF1E1E1E), + level2 = Color(0xFFE3E3E3), lbSignature = lb_purple, lbSignatureSecondary = lb_yellow, lbSignatureInverse = Color(0xFFE5743E), diff --git a/app/src/main/java/org/listenbrainz/android/util/BrainzPlayerExtensions.kt b/app/src/main/java/org/listenbrainz/android/util/BrainzPlayerExtensions.kt index 7848b579..8987653b 100644 --- a/app/src/main/java/org/listenbrainz/android/util/BrainzPlayerExtensions.kt +++ b/app/src/main/java/org/listenbrainz/android/util/BrainzPlayerExtensions.kt @@ -42,7 +42,7 @@ object BrainzPlayerExtensions { inline val MediaMetadataCompat?.toSong get() = this?.description?.let { Song( - mediaID = (if(it.mediaId!="") it.mediaId?.toLong() else Song.emptySong.mediaID)!!, + mediaID = (if (it.mediaId!="") it.mediaId?.toLong() else Song.emptySong.mediaID)!!, title = it.title.toString(), artist = it.subtitle.toString(), uri = it.mediaUri.toString(), diff --git a/app/src/main/java/org/listenbrainz/android/util/SongViewPager.kt b/app/src/main/java/org/listenbrainz/android/util/SongViewPager.kt index 25266c09..25d11467 100644 --- a/app/src/main/java/org/listenbrainz/android/util/SongViewPager.kt +++ b/app/src/main/java/org/listenbrainz/android/util/SongViewPager.kt @@ -113,7 +113,7 @@ fun SongViewPager( state = pagerState, modifier = modifier .fillMaxWidth() - .dynamicBackgroundFromAlbumArt(currentlyPlayingSong.albumArt) + .background(viewModel.playerBackGroundColor) ) { Column( modifier = Modifier diff --git a/app/src/main/java/org/listenbrainz/android/viewmodel/BrainzPlayerViewModel.kt b/app/src/main/java/org/listenbrainz/android/viewmodel/BrainzPlayerViewModel.kt index d4890ce9..6c3746c8 100644 --- a/app/src/main/java/org/listenbrainz/android/viewmodel/BrainzPlayerViewModel.kt +++ b/app/src/main/java/org/listenbrainz/android/viewmodel/BrainzPlayerViewModel.kt @@ -70,6 +70,7 @@ class BrainzPlayerViewModel @Inject constructor( var isSearching by mutableStateOf(false) var playerBackGroundColor by mutableStateOf(Color.Transparent) + private set init { updatePlayerPosition() @@ -86,7 +87,6 @@ class BrainzPlayerViewModel @Inject constructor( it.toSong } _mediaItems.value = Resource(Resource.Status.SUCCESS, songs) - } }) viewModelScope.launch(Dispatchers.IO) { @@ -266,4 +266,69 @@ class BrainzPlayerViewModel @Inject constructor( } } } + + fun playNext(songs: List) { + if (songs.isEmpty()) return + + val currentSongIndex = + appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID == currentlyPlayingSong.value.toSong.mediaID } + ?.plus(1) + if (isPlaying.value && currentSongIndex != null) { + val currentSongs = + appPreferences.currentPlayable?.songs?.toMutableList() + currentSongs?.addAll(currentSongIndex, songs) + appPreferences.currentPlayable = + appPreferences.currentPlayable?.copy( + songs = currentSongs ?: emptyList() + ) + appPreferences.currentPlayable?.songs?.let { + changePlayable( + it, + PlayableType.ALL_SONGS, + appPreferences.currentPlayable?.id ?: 0, + appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID == currentlyPlayingSong.value.toSong.mediaID } + ?: 0, songCurrentPosition.value + ) + } + queueChanged( + currentlyPlayingSong.value.toSong, + isPlaying.value + ) + } else { + // No song is playing, so start playing the selected song + changePlayable( + songs, + PlayableType.SONG, + songs.first().mediaID, + 0, + 0L + ) + playOrToggleSong(songs.first(), true) + } + } + + fun addToQueue( + songs: List + ) { + val currentSongs = + appPreferences.currentPlayable?.songs?.toMutableList() + currentSongs?.addAll(songs) + appPreferences.currentPlayable = + appPreferences.currentPlayable?.copy( + songs = currentSongs ?: emptyList() + ) + appPreferences.currentPlayable?.songs?.let { + changePlayable( + it, + PlayableType.ALL_SONGS, + appPreferences.currentPlayable?.id ?: 0, + appPreferences.currentPlayable?.songs?.indexOfFirst { song -> song.mediaID == currentlyPlayingSong.value.toSong.mediaID } + ?: 0, songCurrentPosition.value + ) + } + queueChanged( + currentlyPlayingSong.value.toSong, + isPlaying.value + ) + } } \ No newline at end of file