list: tweak header/divider object hierarchy
Make a new generic Header/Divider superclass that all headers derive. This allows disc headers to be recognized generically in places like the grid layout manager.
This commit is contained in:
parent
1ee5645780
commit
9883cf1c91
10 changed files with 47 additions and 39 deletions
|
@ -31,10 +31,10 @@ import kotlin.math.min
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
||||
import org.oxycblt.auxio.detail.list.DetailListAdapter
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.ListFragment
|
||||
import org.oxycblt.auxio.list.ListViewModel
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.PlainHeader
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
|
@ -91,7 +91,7 @@ abstract class DetailFragment<P : MusicParent, C : Music> :
|
|||
detailModel.artistSongList.value.getOrElse(it - 1) {
|
||||
return@setFullWidthLookup false
|
||||
}
|
||||
item is Divider || item is Header
|
||||
item is PlainDivider || item is PlainHeader
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -34,10 +34,10 @@ import org.oxycblt.auxio.detail.list.DiscHeader
|
|||
import org.oxycblt.auxio.detail.list.EditHeader
|
||||
import org.oxycblt.auxio.detail.list.SortHeader
|
||||
import org.oxycblt.auxio.list.BasicHeader
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.ListSettings
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.PlainHeader
|
||||
import org.oxycblt.auxio.list.adapter.UpdateInstructions
|
||||
import org.oxycblt.auxio.list.sort.Sort
|
||||
import org.oxycblt.auxio.music.Album
|
||||
|
@ -531,7 +531,7 @@ constructor(
|
|||
list: MutableStateFlow<List<Item>>,
|
||||
instructions: MutableEvent<UpdateInstructions>,
|
||||
replace: Int?,
|
||||
songHeader: (Int) -> Header = { SortHeader(it) }
|
||||
songHeader: (Int) -> PlainHeader = { SortHeader(it) }
|
||||
) {
|
||||
if (detail == null) {
|
||||
parent.value = null
|
||||
|
@ -547,7 +547,7 @@ constructor(
|
|||
if (section is DetailSection.Songs) songHeader(section.stringRes)
|
||||
else BasicHeader(section.stringRes)
|
||||
if (newList.isNotEmpty()) {
|
||||
newList.add(Divider(header))
|
||||
newList.add(PlainDivider(header))
|
||||
}
|
||||
newList.add(header)
|
||||
section.items
|
||||
|
@ -555,7 +555,7 @@ constructor(
|
|||
is DetailSection.Discs -> {
|
||||
val header = SortHeader(section.stringRes)
|
||||
if (newList.isNotEmpty()) {
|
||||
newList.add(Divider(header))
|
||||
newList.add(PlainDivider(header))
|
||||
}
|
||||
newList.add(header)
|
||||
buildList<Item> {
|
||||
|
@ -600,7 +600,7 @@ constructor(
|
|||
val list = mutableListOf<Item>()
|
||||
if (edited.isNotEmpty()) {
|
||||
val header = EditHeader(R.string.lbl_songs)
|
||||
list.add(Divider(header))
|
||||
list.add(PlainDivider(header))
|
||||
list.add(header)
|
||||
list.addAll(edited)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.oxycblt.auxio.IntegerTable
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
||||
import org.oxycblt.auxio.databinding.ItemDiscHeaderBinding
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.SelectableListListener
|
||||
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
||||
|
@ -100,9 +102,9 @@ class AlbumDetailListAdapter(private val listener: Listener<Song>) :
|
|||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
data class DiscHeader(val inner: Disc?) : Item
|
||||
data class DiscHeader(val inner: Disc?) : Header
|
||||
|
||||
data class DiscDivider(val anchor: DiscHeader?) : Item
|
||||
data class DiscDivider(override val anchor: DiscHeader?) : Divider<DiscHeader>
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that displays a [DiscHeader] to delimit different disc groups. Use
|
||||
|
|
|
@ -27,9 +27,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.databinding.ItemSortHeaderBinding
|
||||
import org.oxycblt.auxio.list.BasicHeader
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.PlainHeader
|
||||
import org.oxycblt.auxio.list.SelectableListListener
|
||||
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.list.adapter.SimpleDiffCallback
|
||||
|
@ -55,7 +55,7 @@ abstract class DetailListAdapter(
|
|||
override fun getItemViewType(position: Int) =
|
||||
when (getItem(position)) {
|
||||
// Implement support for headers and sort headers
|
||||
is Divider -> DividerViewHolder.VIEW_TYPE
|
||||
is PlainDivider -> DividerViewHolder.VIEW_TYPE
|
||||
is BasicHeader -> BasicHeaderViewHolder.VIEW_TYPE
|
||||
is SortHeader -> SortHeaderViewHolder.VIEW_TYPE
|
||||
else -> super.getItemViewType(position)
|
||||
|
@ -91,7 +91,7 @@ abstract class DetailListAdapter(
|
|||
object : SimpleDiffCallback<Item>() {
|
||||
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
|
||||
return when {
|
||||
oldItem is Divider && newItem is Divider ->
|
||||
oldItem is PlainDivider && newItem is PlainDivider ->
|
||||
DividerViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
oldItem is BasicHeader && newItem is BasicHeader ->
|
||||
BasicHeaderViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
|
@ -110,7 +110,7 @@ abstract class DetailListAdapter(
|
|||
* @param titleRes The string resource to use as the header title
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
data class SortHeader(@StringRes override val titleRes: Int) : Header
|
||||
data class SortHeader(@StringRes override val titleRes: Int) : PlainHeader
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that displays a [SortHeader] and it's actions. Use [from] to create
|
||||
|
|
|
@ -33,8 +33,8 @@ import org.oxycblt.auxio.IntegerTable
|
|||
import org.oxycblt.auxio.databinding.ItemEditHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemEditableSongBinding
|
||||
import org.oxycblt.auxio.list.EditableListListener
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.PlainHeader
|
||||
import org.oxycblt.auxio.list.adapter.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.list.adapter.SimpleDiffCallback
|
||||
|
@ -140,12 +140,12 @@ class PlaylistDetailListAdapter(private val listener: Listener) :
|
|||
}
|
||||
|
||||
/**
|
||||
* A [Header] variant that displays an edit button.
|
||||
* A [PlainHeader] variant that displays an edit button.
|
||||
*
|
||||
* @param titleRes The string resource to use as the header title
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
data class EditHeader(@StringRes override val titleRes: Int) : Header
|
||||
data class EditHeader(@StringRes override val titleRes: Int) : PlainHeader
|
||||
|
||||
/**
|
||||
* Displays an [EditHeader] and it's actions. Use [from] to create an instance.
|
||||
|
|
|
@ -24,12 +24,14 @@ import androidx.annotation.StringRes
|
|||
/** A marker for something that is a RecyclerView item. Has no functionality on it's own. */
|
||||
interface Item
|
||||
|
||||
interface Header : Item
|
||||
|
||||
/**
|
||||
* A "header" used for delimiting groups of data.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
interface Header : Item {
|
||||
interface PlainHeader : Header {
|
||||
/** The string resource used for the header's title. */
|
||||
val titleRes: Int
|
||||
}
|
||||
|
@ -40,12 +42,16 @@ interface Header : Item {
|
|||
* @param titleRes The string resource used for the header's title.
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
data class BasicHeader(@StringRes override val titleRes: Int) : Header
|
||||
data class BasicHeader(@StringRes override val titleRes: Int) : PlainHeader
|
||||
|
||||
interface Divider<T> : Item {
|
||||
val anchor: T?
|
||||
}
|
||||
|
||||
/**
|
||||
* A divider decoration used to delimit groups of data.
|
||||
*
|
||||
* @param anchor The [Header] this divider should be next to in a list. Used as a way to preserve
|
||||
* divider continuity during list updates.
|
||||
* @param anchor The [PlainHeader] this divider should be next to in a list. Used as a way to
|
||||
* preserve divider continuity during list updates.
|
||||
*/
|
||||
data class Divider(val anchor: Header?) : Item
|
||||
data class PlainDivider(override val anchor: PlainHeader?) : Divider<PlainHeader>
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.oxycblt.auxio.databinding.ItemHeaderBinding
|
|||
import org.oxycblt.auxio.databinding.ItemParentBinding
|
||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||
import org.oxycblt.auxio.list.BasicHeader
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.SelectableListListener
|
||||
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.list.adapter.SimpleDiffCallback
|
||||
|
@ -360,7 +360,7 @@ class BasicHeaderViewHolder private constructor(private val binding: ItemHeaderB
|
|||
}
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that displays a [Divider]. Use [from] to create an instance.
|
||||
* A [RecyclerView.ViewHolder] that displays a [PlainDivider]. Use [from] to create an instance.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
|
@ -381,8 +381,8 @@ class DividerViewHolder private constructor(divider: MaterialDivider) :
|
|||
|
||||
/** A comparator that can be used with DiffUtil. */
|
||||
val DIFF_CALLBACK =
|
||||
object : SimpleDiffCallback<Divider>() {
|
||||
override fun areContentsTheSame(oldItem: Divider, newItem: Divider) =
|
||||
object : SimpleDiffCallback<PlainDivider>() {
|
||||
override fun areContentsTheSame(oldItem: PlainDivider, newItem: PlainDivider) =
|
||||
oldItem.anchor == newItem.anchor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ package org.oxycblt.auxio.search
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.list.BasicHeader
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.SelectableListListener
|
||||
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.list.adapter.SimpleDiffCallback
|
||||
|
@ -57,7 +57,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
|
|||
is Artist -> ArtistViewHolder.VIEW_TYPE
|
||||
is Genre -> GenreViewHolder.VIEW_TYPE
|
||||
is Playlist -> PlaylistViewHolder.VIEW_TYPE
|
||||
is Divider -> DividerViewHolder.VIEW_TYPE
|
||||
is PlainDivider -> DividerViewHolder.VIEW_TYPE
|
||||
is BasicHeader -> BasicHeaderViewHolder.VIEW_TYPE
|
||||
else -> super.getItemViewType(position)
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
|
|||
GenreViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
oldItem is Playlist && newItem is Playlist ->
|
||||
PlaylistViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
oldItem is Divider && newItem is Divider ->
|
||||
oldItem is PlainDivider && newItem is PlainDivider ->
|
||||
DividerViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
oldItem is BasicHeader && newItem is BasicHeader ->
|
||||
BasicHeaderViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
|
|
|
@ -38,11 +38,11 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.detail.Show
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Header
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.ListFragment
|
||||
import org.oxycblt.auxio.list.ListViewModel
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.PlainHeader
|
||||
import org.oxycblt.auxio.list.menu.Menu
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
|
@ -153,7 +153,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
|
|||
searchModel.searchResults.value.getOrElse(it) {
|
||||
return@setFullWidthLookup false
|
||||
}
|
||||
item is Divider || item is Header
|
||||
item is PlainDivider || item is PlainHeader
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.yield
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.list.BasicHeader
|
||||
import org.oxycblt.auxio.list.Divider
|
||||
import org.oxycblt.auxio.list.Item
|
||||
import org.oxycblt.auxio.list.PlainDivider
|
||||
import org.oxycblt.auxio.list.sort.Sort
|
||||
import org.oxycblt.auxio.music.MusicRepository
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
|
@ -152,7 +152,7 @@ constructor(
|
|||
logD("Adding ${it.size} albums to search results")
|
||||
val header = BasicHeader(R.string.lbl_albums)
|
||||
if (isNotEmpty()) {
|
||||
add(Divider(header))
|
||||
add(PlainDivider(header))
|
||||
}
|
||||
|
||||
add(header)
|
||||
|
@ -162,7 +162,7 @@ constructor(
|
|||
logD("Adding ${it.size} playlists to search results")
|
||||
val header = BasicHeader(R.string.lbl_playlists)
|
||||
if (isNotEmpty()) {
|
||||
add(Divider(header))
|
||||
add(PlainDivider(header))
|
||||
}
|
||||
|
||||
add(header)
|
||||
|
@ -172,7 +172,7 @@ constructor(
|
|||
logD("Adding ${it.size} genres to search results")
|
||||
val header = BasicHeader(R.string.lbl_genres)
|
||||
if (isNotEmpty()) {
|
||||
add(Divider(header))
|
||||
add(PlainDivider(header))
|
||||
}
|
||||
|
||||
add(header)
|
||||
|
@ -182,7 +182,7 @@ constructor(
|
|||
logD("Adding ${it.size} songs to search results")
|
||||
val header = BasicHeader(R.string.lbl_songs)
|
||||
if (isNotEmpty()) {
|
||||
add(Divider(header))
|
||||
add(PlainDivider(header))
|
||||
}
|
||||
|
||||
add(header)
|
||||
|
|
Loading…
Reference in a new issue