Cleanup artist songs implementation

Clean up the artist song code to not rely so heavily on a hacky ActionHeader implementation and instead just use it's own viewholder.
This commit is contained in:
OxygenCobalt 2021-04-26 17:20:08 -06:00
parent b9506bcbc3
commit e63122ce3e
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
9 changed files with 50 additions and 38 deletions

View file

@ -45,7 +45,7 @@ class ArtistDetailFragment : DetailFragment() {
} }
val detailAdapter = ArtistDetailAdapter( val detailAdapter = ArtistDetailAdapter(
playbackModel, playbackModel, detailModel,
doOnClick = { data -> doOnClick = { data ->
if (data is Album) { if (data is Album) {
if (!detailModel.isNavigating) { if (!detailModel.isNavigating) {
@ -71,14 +71,8 @@ class ArtistDetailFragment : DetailFragment() {
id = -2, id = -2,
name = getString(R.string.label_songs), name = getString(R.string.label_songs),
icon = detailModel.artistSortMode.value!!.iconRes, icon = detailModel.artistSortMode.value!!.iconRes,
) { btn -> action = detailModel::incrementArtistSortMode
detailModel.incrementArtistSortMode() )
// We'll update the icon of this header object directly so that the state persists
// after the viewholder is recycled.
icon = detailModel.artistSortMode.value!!.iconRes
btn.setImageResource(icon)
}
// --- UI SETUP --- // --- UI SETUP ---

View file

@ -4,9 +4,11 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
import org.oxycblt.auxio.databinding.ItemArtistHeaderBinding import org.oxycblt.auxio.databinding.ItemArtistHeaderBinding
import org.oxycblt.auxio.databinding.ItemArtistSongBinding import org.oxycblt.auxio.databinding.ItemArtistSongBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.logD import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
@ -15,10 +17,10 @@ import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.recycler.DiffCallback import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.ActionHeaderViewHolder
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.recycler.viewholders.Highlightable import org.oxycblt.auxio.recycler.viewholders.Highlightable
import org.oxycblt.auxio.ui.Accent import org.oxycblt.auxio.ui.Accent
import org.oxycblt.auxio.ui.disable
import org.oxycblt.auxio.ui.inflater import org.oxycblt.auxio.ui.inflater
import org.oxycblt.auxio.ui.setTextColorResource import org.oxycblt.auxio.ui.setTextColorResource
@ -28,6 +30,7 @@ import org.oxycblt.auxio.ui.setTextColorResource
*/ */
class ArtistDetailAdapter( class ArtistDetailAdapter(
private val playbackModel: PlaybackViewModel, private val playbackModel: PlaybackViewModel,
private val detailModel: DetailViewModel,
private val doOnClick: (data: BaseModel) -> Unit, private val doOnClick: (data: BaseModel) -> Unit,
private val doOnLongClick: (view: View, data: BaseModel) -> Unit, private val doOnLongClick: (view: View, data: BaseModel) -> Unit,
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) { ) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) {
@ -41,7 +44,7 @@ class ArtistDetailAdapter(
return when (getItem(position)) { return when (getItem(position)) {
is Artist -> ARTIST_HEADER_ITEM_TYPE is Artist -> ARTIST_HEADER_ITEM_TYPE
is Album -> ARTIST_ALBUM_ITEM_TYPE is Album -> ARTIST_ALBUM_ITEM_TYPE
is ActionHeader -> ActionHeaderViewHolder.ITEM_TYPE is ActionHeader -> ARTIST_SONG_HEADER_ITEM_TYPE
is Song -> ARTIST_SONG_ITEM_TYPE is Song -> ARTIST_SONG_ITEM_TYPE
else -> -1 else -> -1
@ -58,7 +61,9 @@ class ArtistDetailAdapter(
ItemArtistAlbumBinding.inflate(parent.context.inflater) ItemArtistAlbumBinding.inflate(parent.context.inflater)
) )
ActionHeaderViewHolder.ITEM_TYPE -> ActionHeaderViewHolder.from(parent.context) ARTIST_SONG_HEADER_ITEM_TYPE -> ArtistSongHeaderViewHolder(
ItemActionHeaderBinding.inflate(parent.context.inflater)
)
ARTIST_SONG_ITEM_TYPE -> ArtistSongViewHolder( ARTIST_SONG_ITEM_TYPE -> ArtistSongViewHolder(
ItemArtistSongBinding.inflate(parent.context.inflater) ItemArtistSongBinding.inflate(parent.context.inflater)
@ -74,7 +79,7 @@ class ArtistDetailAdapter(
when (item) { when (item) {
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)
is ActionHeader -> (holder as ActionHeaderViewHolder).bind(item) is ActionHeader -> (holder as ArtistSongHeaderViewHolder).bind(item)
is Song -> (holder as ArtistSongViewHolder).bind(item) is Song -> (holder as ArtistSongViewHolder).bind(item)
else -> {} else -> {}
@ -195,6 +200,31 @@ class ArtistDetailAdapter(
} }
} }
inner class ArtistSongHeaderViewHolder(
private val binding: ItemActionHeaderBinding
) : BaseViewHolder<ActionHeader>(binding) {
override fun onBind(data: ActionHeader) {
binding.header = data
binding.headerButton.apply {
val sortMode = detailModel.artistSortMode
val artist = detailModel.currentArtist.value!!
setImageResource(sortMode.value!!.iconRes)
setOnClickListener {
data.action() // Should call DetailViewModel.incrementArtistSortMode
setImageResource(sortMode.value!!.iconRes)
}
if (artist.songs.size < 2) {
disable()
}
}
}
}
inner class ArtistSongViewHolder( inner class ArtistSongViewHolder(
private val binding: ItemArtistSongBinding, private val binding: ItemArtistSongBinding,
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable { ) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
@ -218,6 +248,7 @@ class ArtistDetailAdapter(
companion object { companion object {
const val ARTIST_HEADER_ITEM_TYPE = 0xA009 const val ARTIST_HEADER_ITEM_TYPE = 0xA009
const val ARTIST_ALBUM_ITEM_TYPE = 0xA00A const val ARTIST_ALBUM_ITEM_TYPE = 0xA00A
const val ARTIST_SONG_ITEM_TYPE = 0xA00B const val ARTIST_SONG_HEADER_ITEM_TYPE = 0xA00B
const val ARTIST_SONG_ITEM_TYPE = 0xA00C
} }
} }

View file

@ -143,7 +143,7 @@ class GenreDetailAdapter(
} }
companion object { companion object {
const val GENRE_HEADER_ITEM_TYPE = 0xA00C const val GENRE_HEADER_ITEM_TYPE = 0xA00D
const val GENRE_SONG_ITEM_TYPE = 0xA00D const val GENRE_SONG_ITEM_TYPE = 0xA00E
} }
} }

View file

@ -1,7 +1,6 @@
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.net.Uri import android.net.Uri
import android.widget.ImageButton
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
// --- MUSIC MODELS --- // --- MUSIC MODELS ---
@ -174,9 +173,8 @@ data class Genre(
private val mSongs = mutableListOf<Song>() private val mSongs = mutableListOf<Song>()
val songs: List<Song> get() = mSongs val songs: List<Song> get() = mSongs
val resolvedName: String by lazy { val resolvedName =
name.getGenreNameCompat() ?: name name.getGenreNameCompat() ?: name
}
val totalDuration: String get() = val totalDuration: String get() =
songs.sumOf { it.seconds }.toDuration() songs.sumOf { it.seconds }.toDuration()
@ -199,12 +197,12 @@ data class Header(
/** /**
* A data object for a header with an action button. Inherits [BaseModel]. * A data object for a header with an action button. Inherits [BaseModel].
* @property icon The icon ot apply for this header. This can be changed to reflect any change. * @property icon The icon ot apply for this header.
* @property action The callback that will be called when the action button is clicked. * @property action The callback that will be called when the action button is clicked.
*/ */
data class ActionHeader( data class ActionHeader(
override val id: Long = -1, override val id: Long = -1,
override val name: String = "", override val name: String = "",
@DrawableRes var icon: Int, @DrawableRes val icon: Int,
val action: ActionHeader.(button: ImageButton) -> Unit, val action: () -> Unit,
) : BaseModel() ) : BaseModel()

View file

@ -186,7 +186,7 @@ class ActionHeaderViewHolder(
setImageResource(data.icon) setImageResource(data.icon)
setOnClickListener { setOnClickListener {
data.action(data, binding.headerButton) data.action()
} }
} }
} }

View file

@ -10,10 +10,6 @@
name="artist" name="artist"
type="org.oxycblt.auxio.music.Artist" /> type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable <variable
name="playbackModel" name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" /> type="org.oxycblt.auxio.playback.PlaybackViewModel" />

View file

@ -10,10 +10,6 @@
name="artist" name="artist"
type="org.oxycblt.auxio.music.Artist" /> type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable <variable
name="playbackModel" name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" /> type="org.oxycblt.auxio.playback.PlaybackViewModel" />

View file

@ -10,10 +10,6 @@
name="artist" name="artist"
type="org.oxycblt.auxio.music.Artist" /> type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable <variable
name="playbackModel" name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" /> type="org.oxycblt.auxio.playback.PlaybackViewModel" />

View file

@ -50,9 +50,10 @@ To prevent any strange bugs, all integer representations must be unique. A table
0xA008 | AlbumSongViewHolder 0xA008 | AlbumSongViewHolder
0xA009 | ArtistHeaderViewHolder 0xA009 | ArtistHeaderViewHolder
0xA00A | ArtistAlbumViewHolder 0xA00A | ArtistAlbumViewHolder
0xA00B | ArtistSongViewHolder 0xA00B | ArtistSongHeaderViewHolder
0xA00C | GenreHeaderViewHolder 0xA00C | ArtistSongViewHolder
0xA00D | GenreSongViewHolder 0xA00D | GenreHeaderViewHolder
0xA00E | GenreSongViewHolder
0xA0A0 | Auxio notification code 0xA0A0 | Auxio notification code
0xA0C0 | Auxio request code 0xA0C0 | Auxio request code