Add playing indicator to ArtistDetailFragment

Add an indicator that an album is playing in ArtistDetailFragment.
This commit is contained in:
OxygenCobalt 2020-12-30 16:05:40 -07:00
parent 85a8241976
commit 38197344f6
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
5 changed files with 82 additions and 5 deletions

View file

@ -134,7 +134,7 @@ class AlbumDetailFragment : DetailFragment() {
playbackModel.song.observe(viewLifecycleOwner) { song -> playbackModel.song.observe(viewLifecycleOwner) { song ->
if (playbackModel.mode.value == PlaybackMode.IN_ALBUM && if (playbackModel.mode.value == PlaybackMode.IN_ALBUM &&
playbackModel.parent.value!!.id == detailModel.currentAlbum.value!!.id playbackModel.parent.value?.id == detailModel.currentAlbum.value!!.id
) { ) {
detailAdapter.setCurrentSong(song) detailAdapter.setCurrentSong(song)

View file

@ -10,9 +10,12 @@ import androidx.navigation.fragment.navArgs
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.detail.adapters.ArtistDetailAdapter import org.oxycblt.auxio.detail.adapters.ArtistDetailAdapter
import org.oxycblt.auxio.logD import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.state.PlaybackMode
import org.oxycblt.auxio.recycler.Highlightable
import org.oxycblt.auxio.ui.setupAlbumActions import org.oxycblt.auxio.ui.setupAlbumActions
/** /**
@ -104,6 +107,39 @@ class ArtistDetailFragment : DetailFragment() {
} }
} }
// --- PLAYBACKVIEWMODEL SETUP ---
playbackModel.parent.observe(viewLifecycleOwner) { parent ->
if (playbackModel.mode.value == PlaybackMode.IN_ALBUM && parent is Album?) {
detailAdapter.setCurrentAlbum(parent)
lastHolder?.setHighlighted(false)
lastHolder = null
if (parent != null) {
// Use existing data instead of having to re-sort it.
val pos = detailAdapter.currentList.indexOfFirst {
it.name == parent.name
}
// Check if the ViewHolder if this album is visible, and highlight it if so.
binding.detailRecycler.layoutManager?.findViewByPosition(pos)?.let { child ->
binding.detailRecycler.getChildViewHolder(child)?.let {
lastHolder = it as Highlightable
lastHolder?.setHighlighted(true)
}
}
}
} else {
// Clear the viewholders if the mode isn't IN_ALBUM
detailAdapter.setCurrentAlbum(null)
lastHolder?.setHighlighted(false)
lastHolder = null
}
}
logD("Fragment created.") logD("Fragment created.")
return binding.root return binding.root

View file

@ -13,8 +13,11 @@ import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.recycler.DiffCallback import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.Highlightable
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.ui.accent
import org.oxycblt.auxio.ui.disable import org.oxycblt.auxio.ui.disable
import org.oxycblt.auxio.ui.setTextColorResource
/** /**
* An adapter for displaying the [Album]s of an artist. * An adapter for displaying the [Album]s of an artist.
@ -25,6 +28,8 @@ class ArtistDetailAdapter(
private val doOnClick: (data: Album) -> Unit, private val doOnClick: (data: Album) -> Unit,
private val doOnLongClick: (data: Album, view: View) -> Unit, private val doOnLongClick: (data: Album, view: View) -> Unit,
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) { ) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) {
private var currentAlbum: Album? = null
private var lastHolder: Highlightable? = null
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return when (getItem(position)) { return when (getItem(position)) {
@ -54,6 +59,30 @@ class ArtistDetailAdapter(
is Artist -> (holder as ArtistHeaderViewHolder).bind(item) is Artist -> (holder as ArtistHeaderViewHolder).bind(item)
is Album -> (holder as ArtistAlbumViewHolder).bind(item) is Album -> (holder as ArtistAlbumViewHolder).bind(item)
} }
if (currentAlbum != null && position > 0) {
if (getItem(position).id == currentAlbum?.id) {
// Reset the last ViewHolder before assigning the new, correct one to be highlighted
lastHolder?.setHighlighted(false)
lastHolder = (holder as Highlightable)
holder.setHighlighted(true)
} else {
(holder as Highlightable).setHighlighted(false)
}
}
}
/**
* Update the current album that this adapter should be watching for to highlight.
* @param album The [Album] to highlight if found, null to clear any highlighted ViewHolders
*/
fun setCurrentAlbum(album: Album?) {
// Clear out the last ViewHolder as a song update usually signifies that this current
// ViewHolder is likely invalid.
lastHolder?.setHighlighted(false)
lastHolder = null
currentAlbum = album
} }
inner class ArtistHeaderViewHolder( inner class ArtistHeaderViewHolder(
@ -74,13 +103,22 @@ class ArtistDetailAdapter(
// Generic ViewHolder for a detail album // Generic ViewHolder for a detail album
inner class ArtistAlbumViewHolder( inner class ArtistAlbumViewHolder(
private val binding: ItemArtistAlbumBinding, private val binding: ItemArtistAlbumBinding,
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick) { ) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick), Highlightable {
private val normalTextColor = binding.albumName.currentTextColor
override fun onBind(data: Album) { override fun onBind(data: Album) {
binding.album = data binding.album = data
binding.albumName.requestLayout() binding.albumName.requestLayout()
} }
override fun setHighlighted(isHighlighted: Boolean) {
if (isHighlighted) {
binding.albumName.setTextColorResource(accent.first)
} else {
binding.albumName.setTextColor(normalTextColor)
}
}
} }
companion object { companion object {

View file

@ -438,9 +438,11 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
* @param reason (Debug) The reason for this call. * @param reason (Debug) The reason for this call.
*/ */
private fun startForegroundOrNotify(reason: String) { private fun startForegroundOrNotify(reason: String) {
// Don't start the foreground if the playback hasn't started yet AND if the playback hasn't // Don't start the foreground if:
// been restored // - The playback hasnt even started
if (playbackManager.hasPlayed && playbackManager.isRestored) { // - The playback hasnt been restored
// - There is nothing to play
if (playbackManager.hasPlayed && playbackManager.isRestored && playbackManager.song != null) {
logD("Starting foreground/notifying because of $reason") logD("Starting foreground/notifying because of $reason")
if (!isForeground) { if (!isForeground) {

View file

@ -368,6 +368,7 @@ class PlaybackStateManager private constructor() {
forceQueueUpdate() forceQueueUpdate()
mSong = null mSong = null
mParent = null
} }
} }
} }