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