From e63122ce3ec35b0b69ebcc6a9e39f99dc83f9ee6 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 26 Apr 2021 17:20:08 -0600 Subject: [PATCH] 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. --- .../auxio/detail/ArtistDetailFragment.kt | 12 ++---- .../detail/adapters/ArtistDetailAdapter.kt | 41 ++++++++++++++++--- .../detail/adapters/GenreDetailAdapter.kt | 4 +- .../java/org/oxycblt/auxio/music/Models.kt | 10 ++--- .../recycler/viewholders/ModelHolders.kt | 2 +- .../res/layout-land/item_artist_header.xml | 4 -- .../res/layout-large/item_artist_header.xml | 4 -- .../main/res/layout/item_artist_header.xml | 4 -- info/ARCHITECTURE.md | 7 ++-- 9 files changed, 50 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index f9cbdf794..0346f6414 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -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 --- diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt index d0f42ea7b..151dfa28d 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt @@ -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(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(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(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 } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt index 690228237..b097fa587 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt @@ -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 } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/Models.kt b/app/src/main/java/org/oxycblt/auxio/music/Models.kt index 53710f5df..8ad85377c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Models.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Models.kt @@ -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() val songs: List 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() diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt b/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt index 5eafeaa27..55af83fc9 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt @@ -186,7 +186,7 @@ class ActionHeaderViewHolder( setImageResource(data.icon) setOnClickListener { - data.action(data, binding.headerButton) + data.action() } } } diff --git a/app/src/main/res/layout-land/item_artist_header.xml b/app/src/main/res/layout-land/item_artist_header.xml index 3737497ce..5b56f659b 100644 --- a/app/src/main/res/layout-land/item_artist_header.xml +++ b/app/src/main/res/layout-land/item_artist_header.xml @@ -10,10 +10,6 @@ name="artist" type="org.oxycblt.auxio.music.Artist" /> - - diff --git a/app/src/main/res/layout-large/item_artist_header.xml b/app/src/main/res/layout-large/item_artist_header.xml index 58036bfd5..1d476a476 100644 --- a/app/src/main/res/layout-large/item_artist_header.xml +++ b/app/src/main/res/layout-large/item_artist_header.xml @@ -10,10 +10,6 @@ name="artist" type="org.oxycblt.auxio.music.Artist" /> - - diff --git a/app/src/main/res/layout/item_artist_header.xml b/app/src/main/res/layout/item_artist_header.xml index 7352ceec5..f69d409db 100644 --- a/app/src/main/res/layout/item_artist_header.xml +++ b/app/src/main/res/layout/item_artist_header.xml @@ -10,10 +10,6 @@ name="artist" type="org.oxycblt.auxio.music.Artist" /> - - diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md index 1c8e996b8..f54e8457c 100644 --- a/info/ARCHITECTURE.md +++ b/info/ARCHITECTURE.md @@ -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