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(
playbackModel,
playbackModel, detailModel,
doOnClick = { data ->
if (data is Album) {
if (!detailModel.isNavigating) {
@ -71,14 +71,8 @@ class ArtistDetailFragment : DetailFragment() {
id = -2,
name = getString(R.string.label_songs),
icon = detailModel.artistSortMode.value!!.iconRes,
) { btn ->
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)
}
action = detailModel::incrementArtistSortMode
)
// --- UI SETUP ---

View file

@ -4,9 +4,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
import org.oxycblt.auxio.databinding.ItemArtistHeaderBinding
import org.oxycblt.auxio.databinding.ItemArtistSongBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.ActionHeader
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.playback.PlaybackViewModel
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.Highlightable
import org.oxycblt.auxio.ui.Accent
import org.oxycblt.auxio.ui.disable
import org.oxycblt.auxio.ui.inflater
import org.oxycblt.auxio.ui.setTextColorResource
@ -28,6 +30,7 @@ import org.oxycblt.auxio.ui.setTextColorResource
*/
class ArtistDetailAdapter(
private val playbackModel: PlaybackViewModel,
private val detailModel: DetailViewModel,
private val doOnClick: (data: BaseModel) -> Unit,
private val doOnLongClick: (view: View, data: BaseModel) -> Unit,
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) {
@ -41,7 +44,7 @@ class ArtistDetailAdapter(
return when (getItem(position)) {
is Artist -> ARTIST_HEADER_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
else -> -1
@ -58,7 +61,9 @@ class ArtistDetailAdapter(
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(
ItemArtistSongBinding.inflate(parent.context.inflater)
@ -74,7 +79,7 @@ class ArtistDetailAdapter(
when (item) {
is Artist -> (holder as ArtistHeaderViewHolder).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)
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(
private val binding: ItemArtistSongBinding,
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
@ -218,6 +248,7 @@ class ArtistDetailAdapter(
companion object {
const val ARTIST_HEADER_ITEM_TYPE = 0xA009
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 {
const val GENRE_HEADER_ITEM_TYPE = 0xA00C
const val GENRE_SONG_ITEM_TYPE = 0xA00D
const val GENRE_HEADER_ITEM_TYPE = 0xA00D
const val GENRE_SONG_ITEM_TYPE = 0xA00E
}
}

View file

@ -1,7 +1,6 @@
package org.oxycblt.auxio.music
import android.net.Uri
import android.widget.ImageButton
import androidx.annotation.DrawableRes
// --- MUSIC MODELS ---
@ -174,9 +173,8 @@ data class Genre(
private val mSongs = mutableListOf<Song>()
val songs: List<Song> get() = mSongs
val resolvedName: String by lazy {
val resolvedName =
name.getGenreNameCompat() ?: name
}
val totalDuration: String get() =
songs.sumOf { it.seconds }.toDuration()
@ -199,12 +197,12 @@ data class Header(
/**
* 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.
*/
data class ActionHeader(
override val id: Long = -1,
override val name: String = "",
@DrawableRes var icon: Int,
val action: ActionHeader.(button: ImageButton) -> Unit,
@DrawableRes val icon: Int,
val action: () -> Unit,
) : BaseModel()

View file

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

View file

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

View file

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

View file

@ -10,10 +10,6 @@
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
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
0xA009 | ArtistHeaderViewHolder
0xA00A | ArtistAlbumViewHolder
0xA00B | ArtistSongViewHolder
0xA00C | GenreHeaderViewHolder
0xA00D | GenreSongViewHolder
0xA00B | ArtistSongHeaderViewHolder
0xA00C | ArtistSongViewHolder
0xA00D | GenreHeaderViewHolder
0xA00E | GenreSongViewHolder
0xA0A0 | Auxio notification code
0xA0C0 | Auxio request code