From d38da9b89231fd0d5e97085ad613b6a5eb02981e Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 16 Jan 2023 17:43:59 -0700 Subject: [PATCH] list: make list instructions generic Make list instructions generic in preparation for the detail list update. Detail views need their own instructions datatype, so this is meant to allow that to be implemented without issue. --- CHANGELOG.md | 2 +- app/src/main/java/org/oxycblt/auxio/Auxio.kt | 2 +- .../auxio/detail/AlbumDetailFragment.kt | 8 +- .../auxio/detail/ArtistDetailFragment.kt | 8 +- .../auxio/detail/GenreDetailFragment.kt | 8 +- .../auxio/detail/recycler/DetailAdapter.kt | 4 +- .../auxio/home/list/AlbumListFragment.kt | 2 +- .../auxio/home/list/ArtistListFragment.kt | 2 +- .../auxio/home/list/GenreListFragment.kt | 2 +- .../auxio/home/list/SongListFragment.kt | 2 +- .../auxio/list/recycler/DiffAdapter.kt | 34 ++----- .../oxycblt/auxio/list/recycler/ListDiffer.kt | 91 ++++++++++--------- .../list/recycler/PlayingIndicatorAdapter.kt | 6 +- .../recycler/SelectionIndicatorAdapter.kt | 6 +- .../auxio/playback/queue/QueueAdapter.kt | 4 +- .../auxio/playback/queue/QueueViewModel.kt | 4 +- .../org/oxycblt/auxio/search/SearchAdapter.kt | 3 +- .../oxycblt/auxio/search/SearchFragment.kt | 3 +- app/src/main/res/layout/item_header.xml | 6 -- app/src/main/res/layout/item_sort_header.xml | 8 -- 20 files changed, 102 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8a78ecbb..9643080ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,13 @@ #### What's New - Added ability to play/shuffle selections +- Settings UI has been visually refreshed #### What's Improved - Added ability to edit previously played or currently playing items in the queue - Added support for date values formatted as "YYYYMMDD" - Pressing the button will now clear the current selection before navigating back - Added support for non-standard `ARTISTS` tags -- Reworked music folders dialog to be more visually straightforward - Play Next and Add To Queue now start playback if there is no queue to add #### What's Fixed diff --git a/app/src/main/java/org/oxycblt/auxio/Auxio.kt b/app/src/main/java/org/oxycblt/auxio/Auxio.kt index 101132278..bcb8777e8 100644 --- a/app/src/main/java/org/oxycblt/auxio/Auxio.kt +++ b/app/src/main/java/org/oxycblt/auxio/Auxio.kt @@ -35,7 +35,7 @@ import org.oxycblt.auxio.playback.PlaybackSettings import org.oxycblt.auxio.ui.UISettings /** - * Auxio: A simple, rational music player for android. + * A simple, rational music player for android. * @author Alexander Capehart (OxygenCobalt) */ class Auxio : Application(), ImageLoaderFactory { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index c4eccd9c9..1938d58db 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -29,7 +29,9 @@ import com.google.android.material.transition.MaterialSharedAxis import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.AlbumDetailAdapter +import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music @@ -82,7 +84,7 @@ class AlbumDetailFragment : // DetailViewModel handles most initialization from the navigation argument. detailModel.setAlbumUid(args.albumUid) collectImmediately(detailModel.currentAlbum, ::updateAlbum) - collectImmediately(detailModel.albumList, detailAdapter::diffList) + collectImmediately(detailModel.albumList, ::updateList) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(navModel.exploreNavigationItem, ::handleNavigation) @@ -257,6 +259,10 @@ class AlbumDetailFragment : } } + private fun updateList(items: List) { + detailAdapter.submitList(items, UpdateInstructions.DIFF) + } + private fun updateSelection(selected: List) { detailAdapter.setSelected(selected.toSet()) requireBinding().detailSelectionToolbar.updateSelectionAmount(selected.size) 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 5d8c0f806..1bf9aee6c 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -29,7 +29,9 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.ArtistDetailAdapter import org.oxycblt.auxio.detail.recycler.DetailAdapter +import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music @@ -85,7 +87,7 @@ class ArtistDetailFragment : // DetailViewModel handles most initialization from the navigation argument. detailModel.setArtistUid(args.artistUid) collectImmediately(detailModel.currentArtist, ::updateItem) - collectImmediately(detailModel.artistList, detailAdapter::diffList) + collectImmediately(detailModel.artistList, ::updateList) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(navModel.exploreNavigationItem, ::handleNavigation) @@ -233,6 +235,10 @@ class ArtistDetailFragment : } } + private fun updateList(items: List) { + detailAdapter.submitList(items, UpdateInstructions.DIFF) + } + private fun updateSelection(selected: List) { detailAdapter.setSelected(selected.toSet()) requireBinding().detailSelectionToolbar.updateSelectionAmount(selected.size) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index b5701fcf6..a3df41ca0 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -29,7 +29,9 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.DetailAdapter import org.oxycblt.auxio.detail.recycler.GenreDetailAdapter +import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre @@ -84,7 +86,7 @@ class GenreDetailFragment : // DetailViewModel handles most initialization from the navigation argument. detailModel.setGenreUid(args.genreUid) collectImmediately(detailModel.currentGenre, ::updateItem) - collectImmediately(detailModel.genreList, detailAdapter::diffList) + collectImmediately(detailModel.genreList, ::updateList) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(navModel.exploreNavigationItem, ::handleNavigation) @@ -216,6 +218,10 @@ class GenreDetailFragment : } } + private fun updateList(items: List) { + detailAdapter.submitList(items, UpdateInstructions.DIFF) + } + private fun updateSelection(selected: List) { detailAdapter.setSelected(selected.toSet()) requireBinding().detailSelectionToolbar.updateSelectionAmount(selected.size) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt index 789ca2d19..e598b41e1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt @@ -28,6 +28,7 @@ import org.oxycblt.auxio.detail.SortHeader import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.SelectableListListener +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.list.recycler.* import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.util.context @@ -44,7 +45,8 @@ abstract class DetailAdapter( private val listener: Listener<*>, diffCallback: DiffUtil.ItemCallback ) : - SelectionIndicatorAdapter(ListDiffer.Async(diffCallback)), + SelectionIndicatorAdapter( + ListDiffer.Async(diffCallback)), AuxioRecyclerView.SpanSizeLookup { override fun getItemViewType(position: Int) = diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt index be30f78da..7c4122595 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt @@ -149,7 +149,7 @@ class AlbumListFragment : * @param listener An [SelectableListListener] to bind interactions to. */ private class AlbumAdapter(private val listener: SelectableListListener) : - SelectionIndicatorAdapter( + SelectionIndicatorAdapter( ListDiffer.Async(AlbumViewHolder.DIFF_CALLBACK)) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt index 4bdd0728a..7d14a935f 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt @@ -128,7 +128,7 @@ class ArtistListFragment : * @param listener An [SelectableListListener] to bind interactions to. */ private class ArtistAdapter(private val listener: SelectableListListener) : - SelectionIndicatorAdapter( + SelectionIndicatorAdapter( ListDiffer.Async(ArtistViewHolder.DIFF_CALLBACK)) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt index b738bcbb0..fe2352c86 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt @@ -127,7 +127,7 @@ class GenreListFragment : * @param listener An [SelectableListListener] to bind interactions to. */ private class GenreAdapter(private val listener: SelectableListListener) : - SelectionIndicatorAdapter( + SelectionIndicatorAdapter( ListDiffer.Async(GenreViewHolder.DIFF_CALLBACK)) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = GenreViewHolder.from(parent) diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt index 87f7a3407..285b73dbd 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt @@ -160,7 +160,7 @@ class SongListFragment : * @param listener An [SelectableListListener] to bind interactions to. */ private class SongAdapter(private val listener: SelectableListListener) : - SelectionIndicatorAdapter( + SelectionIndicatorAdapter( ListDiffer.Async(SongViewHolder.DIFF_CALLBACK)) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/DiffAdapter.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/DiffAdapter.kt index e6595b325..7642635a2 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/DiffAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/DiffAdapter.kt @@ -18,14 +18,14 @@ package org.oxycblt.auxio.list.recycler import androidx.recyclerview.widget.RecyclerView -import org.oxycblt.auxio.list.UpdateInstructions /** * A [RecyclerView.Adapter] with [ListDiffer] integration. * @param differFactory The [ListDiffer.Factory] that defines the type of [ListDiffer] to use. */ -abstract class DiffAdapter(differFactory: ListDiffer.Factory) : - RecyclerView.Adapter() { +abstract class DiffAdapter( + differFactory: ListDiffer.Factory +) : RecyclerView.Adapter() { private val differ = differFactory.new(@Suppress("LeakingThis") this) final override fun getItemCount() = differ.currentList.size @@ -42,30 +42,12 @@ abstract class DiffAdapter(differFactory: ListD fun getItem(at: Int) = differ.currentList[at] /** - * Dynamically determine how to update the list based on the given [UpdateInstructions]. + * Dynamically determine how to update the list based on the given instructions. * @param newList The new list of [T] items to show. - * @param instructions The [UpdateInstructions] specifying how to update the list. + * @param instructions The instructions specifying how to update the list. + * @param onDone Called when the update process is completed. Defaults to a no-op. */ - fun submitList(newList: List, instructions: UpdateInstructions) { - when (instructions) { - UpdateInstructions.DIFF -> diffList(newList) - UpdateInstructions.REPLACE -> replaceList(newList) - } + fun submitList(newList: List, instructions: I, onDone: () -> Unit = {}) { + differ.submitList(newList, instructions, onDone) } - - /** - * Update this list using DiffUtil. This can simplify the work of updating the list, but can - * also cause erratic behavior. - * @param newList The new list of [T] items to show. - * @param onDone Callback that will be invoked when the update is completed, allowing means to - * reset the state. - */ - fun diffList(newList: List, onDone: () -> Unit = {}) = differ.diffList(newList, onDone) - - /** - * Visually replace the previous list with a new list. This is useful for large diffs that are - * too erratic for [diffList]. - * @param newList The new list of [T] items to show. - */ - fun replaceList(newList: List) = differ.replaceList(newList) } diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/ListDiffer.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/ListDiffer.kt index 5dd924b2f..254df3f13 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/ListDiffer.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/ListDiffer.kt @@ -24,6 +24,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.RecyclerView import java.lang.reflect.Field +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.util.lazyReflectedField import org.oxycblt.auxio.util.requireIs @@ -31,36 +32,28 @@ import org.oxycblt.auxio.util.requireIs * List differ wrapper that provides more flexibility regarding the way lists are updated. * @author Alexander Capehart (OxygenCobalt) */ -interface ListDiffer { +interface ListDiffer { /** The current list of [T] items. */ val currentList: List /** - * Update this list using [DiffUtil]. This can simplify the work of updating the list, but can - * also cause erratic behavior. + * Dynamically determine how to update the list based on the given instructions. * @param newList The new list of [T] items to show. - * @param onDone Callback that will be invoked when the update is completed, allowing means to - * reset the state. + * @param instructions The [UpdateInstructions] specifying how to update the list. + * @param onDone Called when the update process is completed. */ - fun diffList(newList: List, onDone: () -> Unit = {}) - - /** - * Visually replace the previous list with a new list. This is useful for large diffs that are - * too erratic for [diffList]. - * @param newList The new list of [T] items to show. - */ - fun replaceList(newList: List) + fun submitList(newList: List, instructions: I, onDone: () -> Unit) /** * Defines the creation of new [ListDiffer] instances. Allows such [ListDiffer]s to be passed as * arguments without reliance on a `this` [RecyclerView.Adapter]. */ - abstract class Factory { + abstract class Factory { /** * Create a new [ListDiffer] bound to the given [RecyclerView.Adapter]. * @param adapter The [RecyclerView.Adapter] to bind to. */ - abstract fun new(adapter: RecyclerView.Adapter<*>): ListDiffer + abstract fun new(adapter: RecyclerView.Adapter<*>): ListDiffer } /** @@ -69,8 +62,9 @@ interface ListDiffer { * @param diffCallback A [DiffUtil.ItemCallback] to use for item comparison when diffing the * internal list. */ - class Async(private val diffCallback: DiffUtil.ItemCallback) : Factory() { - override fun new(adapter: RecyclerView.Adapter<*>): ListDiffer = + class Async(private val diffCallback: DiffUtil.ItemCallback) : + Factory() { + override fun new(adapter: RecyclerView.Adapter<*>): ListDiffer = RealAsyncListDiffer(AdapterListUpdateCallback(adapter), diffCallback) } @@ -80,16 +74,33 @@ interface ListDiffer { * @param diffCallback A [DiffUtil.ItemCallback] to use for item comparison when diffing the * internal list. */ - class Blocking(private val diffCallback: DiffUtil.ItemCallback) : Factory() { - override fun new(adapter: RecyclerView.Adapter<*>): ListDiffer = + class Blocking(private val diffCallback: DiffUtil.ItemCallback) : + Factory() { + override fun new(adapter: RecyclerView.Adapter<*>): ListDiffer = RealBlockingListDiffer(AdapterListUpdateCallback(adapter), diffCallback) } } +private abstract class RealListDiffer() : ListDiffer { + override fun submitList( + newList: List, + instructions: UpdateInstructions, + onDone: () -> Unit + ) { + when (instructions) { + UpdateInstructions.DIFF -> diffList(newList, onDone) + UpdateInstructions.REPLACE -> replaceList(newList, onDone) + } + } + + protected abstract fun diffList(newList: List, onDone: () -> Unit) + protected abstract fun replaceList(newList: List, onDone: () -> Unit) +} + private class RealAsyncListDiffer( private val updateCallback: ListUpdateCallback, diffCallback: DiffUtil.ItemCallback -) : ListDiffer { +) : RealListDiffer() { private val inner = AsyncListDiffer(updateCallback, AsyncDifferConfig.Builder(diffCallback).build()) @@ -100,21 +111,21 @@ private class RealAsyncListDiffer( inner.submitList(newList, onDone) } - override fun replaceList(newList: List) { - if (inner.currentList == newList) { - // Nothing to do. - return + override fun replaceList(newList: List, onDone: () -> Unit) { + if (inner.currentList != newList) { + // Do possibly the most idiotic thing possible and mutate the internal differ state + // so we don't have to deal with any disjoint list garbage. This should cancel any prior + // updates and correctly set up the list values while still allowing for the same + // visual animation as the blocking replaceList. + val oldListSize = inner.currentList.size + ASD_MAX_GENERATION_FIELD.set( + inner, requireIs(ASD_MAX_GENERATION_FIELD.get(inner)) + 1) + ASD_MUTABLE_LIST_FIELD.set(inner, newList.ifEmpty { null }) + ASD_READ_ONLY_LIST_FIELD.set(inner, newList) + updateCallback.onRemoved(0, oldListSize) + updateCallback.onInserted(0, newList.size) } - // Do possibly the most idiotic thing possible and mutate the internal differ state - // so we don't have to deal with any disjoint list garbage. This should cancel any prior - // updates and correctly set up the list values while still allowing for the same - // visual animation as the blocking replaceList. - val oldListSize = inner.currentList.size - ASD_MAX_GENERATION_FIELD.set(inner, requireIs(ASD_MAX_GENERATION_FIELD.get(inner)) + 1) - ASD_MUTABLE_LIST_FIELD.set(inner, newList.ifEmpty { null }) - ASD_READ_ONLY_LIST_FIELD.set(inner, newList) - updateCallback.onRemoved(0, oldListSize) - updateCallback.onInserted(0, newList.size) + onDone() } private companion object { @@ -129,7 +140,7 @@ private class RealAsyncListDiffer( private class RealBlockingListDiffer( private val updateCallback: ListUpdateCallback, private val diffCallback: DiffUtil.ItemCallback -) : ListDiffer { +) : RealListDiffer() { override var currentList = listOf() override fun diffList(newList: List, onDone: () -> Unit) { @@ -212,13 +223,9 @@ private class RealBlockingListDiffer( onDone() } - override fun replaceList(newList: List) { - if (currentList == newList) { - // Nothing to do. - return + override fun replaceList(newList: List, onDone: () -> Unit) { + if (currentList != newList) { + diffList(listOf()) { diffList(newList, onDone) } } - - diffList(listOf()) - diffList(newList) } } diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt index 12da3c5d9..00b151e29 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt @@ -26,9 +26,9 @@ import org.oxycblt.auxio.util.logD * @param differFactory The [ListDiffer.Factory] that defines the type of [ListDiffer] to use. * @author Alexander Capehart (OxygenCobalt) */ -abstract class PlayingIndicatorAdapter( - differFactory: ListDiffer.Factory -) : DiffAdapter(differFactory) { +abstract class PlayingIndicatorAdapter( + differFactory: ListDiffer.Factory +) : DiffAdapter(differFactory) { // There are actually two states for this adapter: // - The currently playing item, which is usually marked as "selected" and becomes accented. // - Whether playback is ongoing, which corresponds to whether the item's ImageGroup is diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/SelectionIndicatorAdapter.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/SelectionIndicatorAdapter.kt index 6e402878d..a3ab91222 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/SelectionIndicatorAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/SelectionIndicatorAdapter.kt @@ -27,9 +27,9 @@ import org.oxycblt.auxio.music.Music * @param differFactory The [ListDiffer.Factory] that defines the type of [ListDiffer] to use. * @author Alexander Capehart (OxygenCobalt) */ -abstract class SelectionIndicatorAdapter( - differFactory: ListDiffer.Factory -) : PlayingIndicatorAdapter(differFactory) { +abstract class SelectionIndicatorAdapter( + differFactory: ListDiffer.Factory +) : PlayingIndicatorAdapter(differFactory) { private var selectedItems = setOf() override fun onBindViewHolder(holder: VH, position: Int, payloads: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index 1cec07ed3..6d79d818f 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -27,6 +27,7 @@ import com.google.android.material.shape.MaterialShapeDrawable import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.ItemQueueSongBinding import org.oxycblt.auxio.list.EditableListListener +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.list.recycler.DiffAdapter import org.oxycblt.auxio.list.recycler.ListDiffer import org.oxycblt.auxio.list.recycler.PlayingIndicatorAdapter @@ -40,7 +41,8 @@ import org.oxycblt.auxio.util.* * @author Alexander Capehart (OxygenCobalt) */ class QueueAdapter(private val listener: EditableListListener) : - DiffAdapter(ListDiffer.Blocking(QueueSongViewHolder.DIFF_CALLBACK)) { + DiffAdapter( + ListDiffer.Blocking(QueueSongViewHolder.DIFF_CALLBACK)) { // Since PlayingIndicator adapter relies on an item value, we cannot use it for this // adapter, as one item can appear at several points in the UI. Use a similar implementation // with an index value instead. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt index 1c4709e15..575448286 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt @@ -67,14 +67,14 @@ class QueueViewModel : ViewModel(), PlaybackStateManager.Listener { override fun onQueueReordered(queue: Queue) { // Queue changed completely -> Replace queue, update index - instructions = Instructions(UpdateInstructions.REPLACE, null) + instructions = Instructions(UpdateInstructions.REPLACE, queue.index) _queue.value = queue.resolve() _index.value = queue.index } override fun onNewPlayback(queue: Queue, parent: MusicParent?) { // Entirely new queue -> Replace queue, update index - instructions = Instructions(UpdateInstructions.REPLACE, null) + instructions = Instructions(UpdateInstructions.REPLACE, queue.index) _queue.value = queue.resolve() _index.value = queue.index } diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt index edc8d90df..3c21b54cc 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt @@ -29,7 +29,8 @@ import org.oxycblt.auxio.music.* * @author Alexander Capehart (OxygenCobalt) */ class SearchAdapter(private val listener: SelectableListListener) : - SelectionIndicatorAdapter(ListDiffer.Async(DIFF_CALLBACK)), + SelectionIndicatorAdapter( + ListDiffer.Async(DIFF_CALLBACK)), AuxioRecyclerView.SpanSizeLookup { override fun getItemViewType(position: Int) = diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index 1fe364acb..0932f496a 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -31,6 +31,7 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentSearchBinding import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre @@ -153,7 +154,7 @@ class SearchFragment : ListFragment() { // Don't show the RecyclerView (and it's stray overscroll effects) when there // are no results. binding.searchRecycler.isInvisible = results.isEmpty() - searchAdapter.diffList(results.toMutableList()) { + searchAdapter.submitList(results.toMutableList(), UpdateInstructions.DIFF) { // I would make it so that the position is only scrolled back to the top when // the query actually changes instead of once every re-creation event, but sadly // that doesn't seem possible. diff --git a/app/src/main/res/layout/item_header.xml b/app/src/main/res/layout/item_header.xml index 0c718d8fb..aa69cc8ef 100644 --- a/app/src/main/res/layout/item_header.xml +++ b/app/src/main/res/layout/item_header.xml @@ -13,10 +13,4 @@ android:layout_height="wrap_content" tools:text="Songs" /> - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_sort_header.xml b/app/src/main/res/layout/item_sort_header.xml index 3497e4770..ddaeaf3bb 100644 --- a/app/src/main/res/layout/item_sort_header.xml +++ b/app/src/main/res/layout/item_sort_header.xml @@ -12,7 +12,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/spacing_mid_medium" - app:layout_constraintBottom_toTopOf="@id/header_divider" app:layout_constraintEnd_toStartOf="@+id/header_button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -26,14 +25,7 @@ android:layout_marginEnd="@dimen/spacing_mid_medium" android:contentDescription="@string/lbl_sort" app:icon="@drawable/ic_sort_24" - app:layout_constraintBottom_toTopOf="@id/header_divider" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - \ No newline at end of file