home: enable selection across all home lists
Enable (non-functional) selection functionality across all home lists.
This commit is contained in:
parent
6f05697088
commit
c3500b1b24
16 changed files with 90 additions and 40 deletions
|
@ -135,13 +135,11 @@ class DetailViewModel(application: Application) :
|
|||
if (_currentAlbum.value?.uid == uid) return
|
||||
val library = unlikelyToBeNull(musicStore.library)
|
||||
val album = requireNotNull(library.find<Album>(uid)) { "Invalid album id provided " }
|
||||
|
||||
_currentAlbum.value = album
|
||||
refreshAlbumData(album)
|
||||
}
|
||||
|
||||
fun setArtistUid(uid: Music.UID) {
|
||||
logD(uid)
|
||||
if (_currentArtist.value?.uid == uid) return
|
||||
val library = unlikelyToBeNull(musicStore.library)
|
||||
val artist = requireNotNull(library.find<Artist>(uid)) { "Invalid artist id provided" }
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.oxycblt.auxio.detail.DiscHeader
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPlural
|
||||
|
@ -192,8 +192,15 @@ private class AlbumSongViewHolder private constructor(private val binding: ItemA
|
|||
|
||||
binding.songName.text = item.resolveName(binding.context)
|
||||
binding.songDuration.text = item.durationMs.formatDurationMs(false)
|
||||
|
||||
binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||
binding.root.apply {
|
||||
setOnClickListener { listener.onItemClick(item) }
|
||||
setOnLongClickListener {
|
||||
listener.onItemLongClick(item)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.oxycblt.auxio.databinding.ItemSongBinding
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPlural
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.oxycblt.auxio.detail.SortHeader
|
|||
import org.oxycblt.auxio.ui.recycler.AuxioRecyclerView
|
||||
import org.oxycblt.auxio.ui.recycler.Header
|
||||
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
package org.oxycblt.auxio.home
|
||||
|
||||
import android.app.Application
|
||||
import androidx.collection.arraySetOf
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.getAndUpdate
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.home.tabs.Tab
|
||||
import org.oxycblt.auxio.music.Album
|
||||
|
|
|
@ -32,9 +32,9 @@ import org.oxycblt.auxio.music.Sort
|
|||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.playback.secsToMs
|
||||
import org.oxycblt.auxio.ui.recycler.AlbumViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
|
||||
|
@ -56,6 +56,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
|
|||
}
|
||||
|
||||
collectImmediately(homeModel.albums, homeAdapter::replaceList)
|
||||
collectImmediately(homeModel.selected, homeAdapter::updateSelection)
|
||||
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handleParent)
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
|
|||
}
|
||||
|
||||
private class AlbumAdapter(private val listener: MenuItemListener) :
|
||||
PlayingIndicatorAdapter<AlbumViewHolder>() {
|
||||
SelectionIndicatorAdapter<AlbumViewHolder>() {
|
||||
private val differ = SyncListDiffer(this, AlbumViewHolder.DIFFER)
|
||||
|
||||
override val currentList: List<Item>
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.oxycblt.auxio.music.MusicParent
|
|||
import org.oxycblt.auxio.music.Sort
|
||||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.ui.recycler.ArtistViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.nonZeroOrNull
|
||||
|
@ -52,6 +52,7 @@ class ArtistListFragment : HomeListFragment<Artist>() {
|
|||
}
|
||||
|
||||
collectImmediately(homeModel.artists, homeAdapter::replaceList)
|
||||
collectImmediately(homeModel.selected, homeAdapter::updateSelection)
|
||||
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handleParent)
|
||||
}
|
||||
|
||||
|
@ -94,7 +95,7 @@ class ArtistListFragment : HomeListFragment<Artist>() {
|
|||
}
|
||||
|
||||
private class ArtistAdapter(private val listener: MenuItemListener) :
|
||||
PlayingIndicatorAdapter<ArtistViewHolder>() {
|
||||
SelectionIndicatorAdapter<ArtistViewHolder>() {
|
||||
private val differ = SyncListDiffer(this, ArtistViewHolder.DIFFER)
|
||||
|
||||
override val currentList: List<Item>
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.oxycblt.auxio.music.MusicParent
|
|||
import org.oxycblt.auxio.music.Sort
|
||||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.SelectionIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
|
||||
|
@ -51,6 +51,7 @@ class GenreListFragment : HomeListFragment<Genre>() {
|
|||
}
|
||||
|
||||
collectImmediately(homeModel.genres, homeAdapter::replaceList)
|
||||
collectImmediately(homeModel.selected, homeAdapter::updateSelection)
|
||||
collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handlePlayback)
|
||||
}
|
||||
|
||||
|
@ -93,7 +94,7 @@ class GenreListFragment : HomeListFragment<Genre>() {
|
|||
}
|
||||
|
||||
private class GenreAdapter(private val listener: MenuItemListener) :
|
||||
PlayingIndicatorAdapter<GenreViewHolder>() {
|
||||
SelectionIndicatorAdapter<GenreViewHolder>() {
|
||||
private val differ = SyncListDiffer(this, GenreViewHolder.DIFFER)
|
||||
|
||||
override val currentList: List<Item>
|
||||
|
|
|
@ -23,7 +23,6 @@ import androidx.fragment.app.Fragment
|
|||
import org.oxycblt.auxio.databinding.FragmentHomeListBinding
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicMode
|
||||
import org.oxycblt.auxio.ui.fastscroll.FastScrollRecyclerView
|
||||
import org.oxycblt.auxio.ui.fragment.MenuFragment
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
|
@ -85,5 +84,4 @@ abstract class HomeListFragment<T : Item> :
|
|||
onItemClick(item)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.oxycblt.auxio.music.Sort
|
|||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.playback.secsToMs
|
||||
import org.oxycblt.auxio.settings.Settings
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.SelectionIndicatorAdapter
|
||||
|
|
|
@ -63,5 +63,5 @@ class TabDragCallback(private val adapter: TabAdapter) : ItemTouchHelper.Callbac
|
|||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
||||
|
||||
// We use a custom drag handle, so disable the long press action.
|
||||
override fun isLongPressDragEnabled(): Boolean = false
|
||||
override fun isLongPressDragEnabled() = false
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.oxycblt.auxio.ui.recycler.AuxioRecyclerView
|
|||
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.Header
|
||||
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.Item
|
||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.Context
|
|||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.view.WindowInsets
|
||||
import android.widget.Checkable
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
|
|
|
@ -96,8 +96,8 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
|||
}
|
||||
|
||||
/**
|
||||
* ViewHolder that correctly resizes the item to match the parent width, which it is not normally
|
||||
* in dialogs.
|
||||
* ViewHolder that correctly resizes the item to match the parent width, which it is not normally in
|
||||
* dialogs.
|
||||
*/
|
||||
abstract class DialogViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
||||
init {
|
||||
|
|
|
@ -1,22 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Auxio Project
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.ui.recycler
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* An adapter that implements selection indicators.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
abstract class SelectionIndicatorAdapter<VH : RecyclerView.ViewHolder> : PlayingIndicatorAdapter<VH>() {
|
||||
abstract class SelectionIndicatorAdapter<VH : RecyclerView.ViewHolder> :
|
||||
PlayingIndicatorAdapter<VH>() {
|
||||
private var selectedItems = setOf<Music>()
|
||||
|
||||
override fun onBindViewHolder(
|
||||
holder: VH,
|
||||
position: Int,
|
||||
payloads: List<Any>
|
||||
) {
|
||||
override fun onBindViewHolder(holder: VH, position: Int, payloads: List<Any>) {
|
||||
super.onBindViewHolder(holder, position, payloads)
|
||||
|
||||
if (holder is ViewHolder) {
|
||||
|
@ -53,4 +66,3 @@ abstract class SelectionIndicatorAdapter<VH : RecyclerView.ViewHolder> : Playing
|
|||
abstract fun updateSelectionIndicator(isSelected: Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPlural
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* The shared ViewHolder for a [Song].
|
||||
|
@ -45,7 +44,13 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
|||
binding.songInfo.text = item.resolveArtistContents(binding.context)
|
||||
|
||||
binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||
binding.root.apply {
|
||||
setOnClickListener { listener.onItemClick(item) }
|
||||
setOnLongClickListener {
|
||||
listener.onItemLongClick(item)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||
|
@ -54,7 +59,6 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
|||
}
|
||||
|
||||
override fun updateSelectionIndicator(isSelected: Boolean) {
|
||||
logD("Selected")
|
||||
binding.root.isActivated = isSelected
|
||||
}
|
||||
|
||||
|
@ -76,14 +80,21 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
|||
* @author OxygenCobalt
|
||||
*/
|
||||
class AlbumViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||
SelectionIndicatorAdapter.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: Album, listener: MenuItemListener) {
|
||||
binding.parentImage.bind(item)
|
||||
binding.parentName.text = item.resolveName(binding.context)
|
||||
binding.parentInfo.text = item.resolveArtistContents(binding.context)
|
||||
|
||||
binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||
binding.root.apply {
|
||||
setOnClickListener { listener.onItemClick(item) }
|
||||
setOnLongClickListener {
|
||||
listener.onItemLongClick(item)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||
|
@ -91,6 +102,10 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding
|
|||
binding.parentImage.isPlaying = isPlaying
|
||||
}
|
||||
|
||||
override fun updateSelectionIndicator(isSelected: Boolean) {
|
||||
binding.root.isActivated = isSelected
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = IntegerTable.VIEW_TYPE_ALBUM
|
||||
|
||||
|
@ -111,7 +126,7 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding
|
|||
* @author OxygenCobalt
|
||||
*/
|
||||
class ArtistViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||
SelectionIndicatorAdapter.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: Artist, listener: MenuItemListener) {
|
||||
binding.parentImage.bind(item)
|
||||
|
@ -129,7 +144,13 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
|||
}
|
||||
|
||||
binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||
binding.root.apply {
|
||||
setOnClickListener { listener.onItemClick(item) }
|
||||
setOnLongClickListener {
|
||||
listener.onItemLongClick(item)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||
|
@ -137,6 +158,10 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
|||
binding.parentImage.isPlaying = isPlaying
|
||||
}
|
||||
|
||||
override fun updateSelectionIndicator(isSelected: Boolean) {
|
||||
binding.root.isActivated = isSelected
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = IntegerTable.VIEW_TYPE_ARTIST
|
||||
|
||||
|
@ -157,7 +182,7 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
|||
* @author OxygenCobalt
|
||||
*/
|
||||
class GenreViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||
SelectionIndicatorAdapter.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: Genre, listener: MenuItemListener) {
|
||||
binding.parentImage.bind(item)
|
||||
|
@ -168,7 +193,14 @@ class GenreViewHolder private constructor(private val binding: ItemParentBinding
|
|||
binding.context.getPlural(R.plurals.fmt_artist_count, item.artists.size),
|
||||
binding.context.getPlural(R.plurals.fmt_song_count, item.songs.size))
|
||||
binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||
|
||||
binding.root.apply {
|
||||
setOnClickListener { listener.onItemClick(item) }
|
||||
setOnLongClickListener {
|
||||
listener.onItemLongClick(item)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||
|
@ -176,6 +208,10 @@ class GenreViewHolder private constructor(private val binding: ItemParentBinding
|
|||
binding.parentImage.isPlaying = isPlaying
|
||||
}
|
||||
|
||||
override fun updateSelectionIndicator(isSelected: Boolean) {
|
||||
binding.root.isActivated = isSelected
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = IntegerTable.VIEW_TYPE_GENRE
|
||||
|
||||
|
|
Loading…
Reference in a new issue