ui: handle playing indicator edge cases

Handle two edge cases identified with the playing indicator behavior:
1. When enqueing songs from another parent, the prior parent is still
indicates as "playing" when it kind-of isn't.
2. When playback is stopped, the parent is not reset, and thus will
still be indicated as "playing" after the song has disappeared. This
is rarer and should be resolved in other ways, but the solution to
1 also fixes this.

Resolves #380.
This commit is contained in:
Alexander Capehart 2023-05-25 13:10:49 -06:00
parent 21a6b97bfa
commit c2def19aee
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 49 additions and 36 deletions

View file

@ -254,14 +254,14 @@ class ArtistDetailFragment :
val currentArtist = unlikelyToBeNull(detailModel.currentArtist.value)
val playingItem =
when (parent) {
// Always highlight a playing album if it's from this artist.
is Album -> parent
// Always highlight a playing album if it's from this artist, and if the currently
// playing song is contained within.
is Album -> parent.takeIf { song?.album == it }
// If the parent is the artist itself, use the currently playing song.
currentArtist -> song
// Nothing is playing from this artist.
else -> null
}
artistListAdapter.setPlaying(playingItem, isPlaying)
}

View file

@ -239,15 +239,18 @@ class GenreDetailFragment :
}
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
var playingMusic: Music? = null
if (parent is Artist) {
playingMusic = parent
}
// Prefer songs that might be playing from this genre.
if (parent is Genre && parent.uid == unlikelyToBeNull(detailModel.currentGenre.value).uid) {
playingMusic = song
}
genreListAdapter.setPlaying(playingMusic, isPlaying)
val currentGenre = unlikelyToBeNull(detailModel.currentGenre.value)
val playingItem =
when (parent) {
// Always highlight a playing artist if it's from this genre, and if the currently
// playing song is contained within.
is Artist -> parent.takeIf { song?.run { artists.contains(it) } ?: false }
// If the parent is the artist itself, use the currently playing song.
currentGenre -> song
// Nothing is playing from this artist.
else -> null
}
genreListAdapter.setPlaying(playingItem, isPlaying)
}
private fun handleNavigation(item: Music?) {

View file

@ -41,6 +41,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.navigation.NavigationViewModel
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.formatDurationMs
@ -82,7 +83,8 @@ class AlbumListFragment :
collectImmediately(homeModel.albumsList, ::updateAlbums)
collectImmediately(selectionModel.selected, ::updateSelection)
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
collectImmediately(
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
}
override fun onDestroyBinding(binding: FragmentHomeListBinding) {
@ -151,9 +153,11 @@ class AlbumListFragment :
albumAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
}
private fun updatePlayback(parent: MusicParent?, isPlaying: Boolean) {
// If an album is playing, highlight it within this adapter.
albumAdapter.setPlaying(parent as? Album, isPlaying)
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
// Only highlight the album if it is currently playing, and if the currently
// playing song is also contained within.
val playlist = (parent as? Album)?.takeIf { song?.album == it }
albumAdapter.setPlaying(playlist, isPlaying)
}
/**

View file

@ -39,6 +39,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.navigation.NavigationViewModel
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.formatDurationMs
@ -78,7 +79,8 @@ class ArtistListFragment :
collectImmediately(homeModel.artistsList, ::updateArtists)
collectImmediately(selectionModel.selected, ::updateSelection)
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
collectImmediately(
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
}
override fun onDestroyBinding(binding: FragmentHomeListBinding) {
@ -128,9 +130,11 @@ class ArtistListFragment :
artistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
}
private fun updatePlayback(parent: MusicParent?, isPlaying: Boolean) {
// If an artist is playing, highlight it within this adapter.
artistAdapter.setPlaying(parent as? Artist, isPlaying)
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
// Only highlight the artist if it is currently playing, and if the currently
// playing song is also contained within.
val playlist = (parent as? Artist)?.takeIf { song?.run { artists.contains(it) } ?: false }
artistAdapter.setPlaying(playlist, isPlaying)
}
/**

View file

@ -39,6 +39,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.navigation.NavigationViewModel
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.formatDurationMs
@ -77,7 +78,8 @@ class GenreListFragment :
collectImmediately(homeModel.genresList, ::updateGenres)
collectImmediately(selectionModel.selected, ::updateSelection)
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
collectImmediately(
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
}
override fun onDestroyBinding(binding: FragmentHomeListBinding) {
@ -127,9 +129,11 @@ class GenreListFragment :
genreAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
}
private fun updatePlayback(parent: MusicParent?, isPlaying: Boolean) {
// If a genre is playing, highlight it within this adapter.
genreAdapter.setPlaying(parent as? Genre, isPlaying)
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
// Only highlight the genre if it is currently playing, and if the currently
// playing song is also contained within.
val playlist = (parent as? Genre)?.takeIf { song?.run { genres.contains(it) } ?: false }
genreAdapter.setPlaying(playlist, isPlaying)
}
/**

View file

@ -38,6 +38,7 @@ import org.oxycblt.auxio.music.MusicMode
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.navigation.NavigationViewModel
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.formatDurationMs
@ -48,8 +49,6 @@ import org.oxycblt.auxio.util.logD
* A [ListFragment] that shows a list of [Playlist]s.
*
* @author Alexander Capehart (OxygenCobalt)
*
* TODO: Show a placeholder when there are no playlists.
*/
class PlaylistListFragment :
ListFragment<Playlist, FragmentHomeListBinding>(),
@ -77,7 +76,8 @@ class PlaylistListFragment :
collectImmediately(homeModel.playlistsList, ::updatePlaylists)
collectImmediately(selectionModel.selected, ::updateSelection)
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
collectImmediately(
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
}
override fun onDestroyBinding(binding: FragmentHomeListBinding) {
@ -128,9 +128,11 @@ class PlaylistListFragment :
playlistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
}
private fun updatePlayback(parent: MusicParent?, isPlaying: Boolean) {
// If a playlist is playing, highlight it within this adapter.
playlistAdapter.setPlaying(parent as? Playlist, isPlaying)
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
// Only highlight the playlist if it is currently playing, and if the currently
// playing song is also contained within.
val playlist = (parent as? Playlist)?.takeIf { it.songs.contains(song) } ?: return
playlistAdapter.setPlaying(playlist, isPlaying)
}
/**

View file

@ -155,12 +155,8 @@ class SongListFragment :
}
private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) {
if (parent == null) {
songAdapter.setPlaying(song, isPlaying)
} else {
// Ignore playback that is not from all songs
songAdapter.setPlaying(null, isPlaying)
}
// Only indicate playback that is from all songs
songAdapter.setPlaying(song.takeIf { parent == null }, isPlaying)
}
/**