From 6c59a03042f5342b3c68ae31e857d8750baea49d Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Tue, 26 Jul 2022 10:57:24 -0600 Subject: [PATCH] queue: rework internal queue system Rework the queue internally to decouple the queue from playback and better respond to reshuffling. This is being implemented under the assumption that I will be implementing the sliding queue eventually. --- .../auxio/detail/recycler/DetailAdapter.kt | 10 +- .../auxio/playback/PlaybackPanelFragment.kt | 6 -- .../auxio/playback/PlaybackViewModel.kt | 45 --------- .../auxio/playback/queue/QueueAdapter.kt | 2 +- .../auxio/playback/queue/QueueDragCallback.kt | 3 +- .../auxio/playback/queue/QueueFragment.kt | 25 +++-- .../auxio/playback/queue/QueueViewModel.kt | 96 +++++++++++++++++++ .../playback/state/PlaybackStateManager.kt | 17 +++- .../playback/system/MediaSessionComponent.kt | 46 +++++++-- .../org/oxycblt/auxio/search/SearchAdapter.kt | 10 +- .../oxycblt/auxio/ui/recycler/ViewHolders.kt | 6 +- app/src/main/res/layout/item_queue_song.xml | 1 + app/src/main/res/values/strings.xml | 2 + 13 files changed, 178 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt 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 dc8011765..49f1d7dcf 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,10 +28,10 @@ import org.oxycblt.auxio.databinding.ItemSortHeaderBinding import org.oxycblt.auxio.ui.recycler.AsyncBackingData import org.oxycblt.auxio.ui.recycler.BindingViewHolder import org.oxycblt.auxio.ui.recycler.Header +import org.oxycblt.auxio.ui.recycler.HeaderViewHolder import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.ui.recycler.MultiAdapter -import org.oxycblt.auxio.ui.recycler.NewHeaderViewHolder import org.oxycblt.auxio.ui.recycler.SimpleItemCallback import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.inflater @@ -70,14 +70,14 @@ abstract class DetailAdapter( override fun getCreatorFromItem(item: Item) = when (item) { - is Header -> NewHeaderViewHolder.CREATOR + is Header -> HeaderViewHolder.CREATOR is SortHeader -> SortHeaderViewHolder.CREATOR else -> null } override fun getCreatorFromViewType(viewType: Int) = when (viewType) { - NewHeaderViewHolder.CREATOR.viewType -> NewHeaderViewHolder.CREATOR + HeaderViewHolder.CREATOR.viewType -> HeaderViewHolder.CREATOR SortHeaderViewHolder.CREATOR.viewType -> SortHeaderViewHolder.CREATOR else -> null } @@ -90,7 +90,7 @@ abstract class DetailAdapter( ) { if (payload.isEmpty()) { when (item) { - is Header -> (viewHolder as NewHeaderViewHolder).bind(item, Unit) + is Header -> (viewHolder as HeaderViewHolder).bind(item, Unit) is SortHeader -> (viewHolder as SortHeaderViewHolder).bind(item, listener) } } @@ -111,7 +111,7 @@ abstract class DetailAdapter( override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean { return when { oldItem is Header && newItem is Header -> - NewHeaderViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) + HeaderViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) oldItem is SortHeader && newItem is SortHeader -> SortHeaderViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) else -> false diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt index 72ed9ecc3..40ba5603f 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt @@ -114,8 +114,6 @@ class PlaybackPanelFragment : collectImmediately(playbackModel.repeatMode, ::updateRepeat) collectImmediately(playbackModel.isPlaying, ::updatePlaying) collectImmediately(playbackModel.isShuffled, ::updateShuffled) - collectImmediately(playbackModel.nextUp, ::updateNextUp) - logD("Fragment Created") } @@ -195,8 +193,4 @@ class PlaybackPanelFragment : private fun updateShuffled(isShuffled: Boolean) { requireBinding().playbackShuffle.isActivated = isShuffled } - - private fun updateNextUp(nextUp: List) { - queueItem.isEnabled = nextUp.isNotEmpty() - } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt index 3d98735da..be71292ff 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -36,7 +36,6 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.util.application -import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logE /** @@ -77,11 +76,6 @@ class PlaybackViewModel(application: Application) : val isShuffled: StateFlow get() = _isShuffled - private val _nextUp = MutableStateFlow(listOf()) - /** The queue, without the previous items. */ - val nextUp: StateFlow> - get() = _nextUp - init { musicStore.addCallback(this) playbackManager.addCallback(this) @@ -196,39 +190,6 @@ class PlaybackViewModel(application: Application) : playbackManager.prev() } - /** - * Go to an item in the queue using it's recyclerview adapter index. No-ops if out of bounds. - */ - fun goto(adapterIndex: Int) { - val index = adapterIndex + (playbackManager.queue.size - _nextUp.value.size) - logD(adapterIndex) - logD(playbackManager.queue.size - _nextUp.value.size) - - if (index in playbackManager.queue.indices) { - playbackManager.goto(index) - } - } - - /** Remove a queue item using it's recyclerview adapter index. */ - fun removeQueueDataItem(adapterIndex: Int) { - val index = adapterIndex + (playbackManager.queue.size - _nextUp.value.size) - if (index in playbackManager.queue.indices) { - playbackManager.removeQueueItem(index) - } - } - /** Move queue items using their recyclerview adapter indices. */ - fun moveQueueDataItems(adapterFrom: Int, adapterTo: Int): Boolean { - val delta = (playbackManager.queue.size - _nextUp.value.size) - val from = adapterFrom + delta - val to = adapterTo + delta - if (from in playbackManager.queue.indices && to in playbackManager.queue.indices) { - playbackManager.moveQueueItem(from, to) - return true - } - - return false - } - /** Add a [Song] to the top of the queue. */ fun playNext(song: Song) { playbackManager.playNext(song) @@ -334,17 +295,11 @@ class PlaybackViewModel(application: Application) : override fun onIndexMoved(index: Int) { _song.value = playbackManager.song - _nextUp.value = playbackManager.queue.slice(index + 1 until playbackManager.queue.size) - } - - override fun onQueueChanged(index: Int, queue: List) { - _nextUp.value = queue.slice(index + 1 until queue.size) } override fun onNewPlayback(index: Int, queue: List, parent: MusicParent?) { _song.value = playbackManager.song _parent.value = playbackManager.parent - _nextUp.value = queue.slice(index + 1 until queue.size) } override fun onPositionChanged(positionMs: Long) { 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 832dace5a..cb6de1e66 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 @@ -31,7 +31,7 @@ import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.ui.recycler.* import org.oxycblt.auxio.util.* -class QueueAdapter(private val listener: QueueItemListener) : +class QueueAdapter(listener: QueueItemListener) : MonoAdapter(listener) { override val data = SyncBackingData(this, QueueSongViewHolder.DIFFER) override val creator = QueueSongViewHolder.CREATOR diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt index 8892f18d2..a1471f0be 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt @@ -27,7 +27,6 @@ import kotlin.math.max import kotlin.math.min import kotlin.math.sign import org.oxycblt.auxio.R -import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.getDimenSafe import org.oxycblt.auxio.util.logD @@ -37,7 +36,7 @@ import org.oxycblt.auxio.util.logD * hot garbage. This shouldn't have *too many* UI bugs. I hope. * @author OxygenCobalt */ -class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() { +class QueueDragCallback(private val playbackModel: QueueViewModel) : ItemTouchHelper.Callback() { private var shouldLift = true override fun getMovementFlags( diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index 1489e2c12..34612f674 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -20,14 +20,12 @@ package org.oxycblt.auxio.playback.queue import android.os.Bundle import android.view.LayoutInflater import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.FragmentQueueBinding -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.fragment.ViewBindingFragment -import org.oxycblt.auxio.util.androidActivityViewModels import org.oxycblt.auxio.util.collectImmediately /** @@ -35,10 +33,10 @@ import org.oxycblt.auxio.util.collectImmediately * @author OxygenCobalt */ class QueueFragment : ViewBindingFragment(), QueueItemListener { - private val playbackModel: PlaybackViewModel by androidActivityViewModels() + private val queueModel: QueueViewModel by activityViewModels() private val queueAdapter = QueueAdapter(this) private val touchHelper: ItemTouchHelper by lifecycleObject { - ItemTouchHelper(QueueDragCallback(playbackModel)) + ItemTouchHelper(QueueDragCallback(queueModel)) } override fun onCreateBinding(inflater: LayoutInflater) = FragmentQueueBinding.inflate(inflater) @@ -53,7 +51,7 @@ class QueueFragment : ViewBindingFragment(), QueueItemList // --- VIEWMODEL SETUP ---- - collectImmediately(playbackModel.nextUp, ::updateQueue) + collectImmediately(queueModel.queue, ::updateQueue) } override fun onDestroyBinding(binding: FragmentQueueBinding) { @@ -62,19 +60,20 @@ class QueueFragment : ViewBindingFragment(), QueueItemList } override fun onClick(viewHolder: RecyclerView.ViewHolder) { - playbackModel.goto(viewHolder.bindingAdapterPosition) + queueModel.goto(viewHolder.bindingAdapterPosition) } override fun onPickUp(viewHolder: RecyclerView.ViewHolder) { touchHelper.startDrag(viewHolder) } - private fun updateQueue(queue: List) { - if (queue.isEmpty()) { - findNavController().navigateUp() - return + private fun updateQueue(queue: QueueViewModel.QueueData) { + if (queue.nonTrivial) { + // nonTrivial implies that using a synced submitList would be slow, replace the list + // instead. + queueAdapter.data.replaceList(queue.queue) + } else { + queueAdapter.data.submitList(queue.queue) } - - queueAdapter.data.submitList(queue.toMutableList()) } } 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 new file mode 100644 index 000000000..0f09405eb --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueViewModel.kt @@ -0,0 +1,96 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.playback.queue + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import org.oxycblt.auxio.music.MusicParent +import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.playback.state.PlaybackStateManager +import org.oxycblt.auxio.util.logD + +class QueueViewModel : ViewModel(), PlaybackStateManager.Callback { + private val playbackManager = PlaybackStateManager.getInstance() + + data class QueueData(val queue: List, val nonTrivial: Boolean) + + private val _queue = MutableStateFlow(QueueData(listOf(), false)) + val queue: StateFlow = _queue + + init { + playbackManager.addCallback(this) + } + + /** + * Go to an item in the queue using it's recyclerview adapter index. No-ops if out of bounds. + */ + fun goto(adapterIndex: Int) { + val index = adapterIndex + (playbackManager.queue.size - _queue.value.queue.size) + logD(adapterIndex) + logD(playbackManager.queue.size - _queue.value.queue.size) + + if (index in playbackManager.queue.indices) { + playbackManager.goto(index) + } + } + + /** Remove a queue item using it's recyclerview adapter index. */ + fun removeQueueDataItem(adapterIndex: Int) { + val index = adapterIndex + (playbackManager.queue.size - _queue.value.queue.size) + if (index in playbackManager.queue.indices) { + playbackManager.removeQueueItem(index) + } + } + /** Move queue items using their recyclerview adapter indices. */ + fun moveQueueDataItems(adapterFrom: Int, adapterTo: Int): Boolean { + val delta = (playbackManager.queue.size - _queue.value.queue.size) + val from = adapterFrom + delta + val to = adapterTo + delta + if (from in playbackManager.queue.indices && to in playbackManager.queue.indices) { + playbackManager.moveQueueItem(from, to) + return true + } + + return false + } + + override fun onIndexMoved(index: Int) { + _queue.value = QueueData(generateQueue(index, playbackManager.queue), false) + } + + override fun onQueueChanged(queue: List) { + _queue.value = QueueData(generateQueue(playbackManager.index, queue), false) + } + + override fun onQueueReworked(index: Int, queue: List) { + _queue.value = QueueData(generateQueue(index, queue), true) + } + + override fun onNewPlayback(index: Int, queue: List, parent: MusicParent?) { + _queue.value = QueueData(generateQueue(index, queue), true) + } + + private fun generateQueue(index: Int, queue: List) = + queue.slice(index + 1..playbackManager.queue.lastIndex) + + override fun onCleared() { + super.onCleared() + playbackManager.removeCallback(this) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index c0f16e0f5..66dc8fcbc 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -280,7 +280,7 @@ class PlaybackStateManager private constructor() { val library = musicStore.library ?: return val song = song ?: return applyNewQueue(library, settings, shuffled, song) - notifyQueueChanged() + notifyQueueReworked() notifyShuffledChanged() } @@ -464,7 +464,13 @@ class PlaybackStateManager private constructor() { private fun notifyQueueChanged() { for (callback in callbacks) { - callback.onQueueChanged(index, queue) + callback.onQueueChanged(queue) + } + } + + private fun notifyQueueReworked() { + for (callback in callbacks) { + callback.onQueueReworked(index, queue) } } @@ -529,8 +535,11 @@ class PlaybackStateManager private constructor() { /** Called when the index is moved, but the queue does not change. This changes the song. */ fun onIndexMoved(index: Int) {} - /** Called when the queue and/or index changed, but the song has not. */ - fun onQueueChanged(index: Int, queue: List) {} + /** Called when the queue has changed in a way that does not change the index or song. */ + fun onQueueChanged(queue: List) {} + + /** Called when the queue and index has changed, but the song has not changed.. */ + fun onQueueReworked(index: Int, queue: List) {} /** Called when playback is changed completely, with a new index, queue, and parent. */ fun onNewPlayback(index: Int, queue: List, parent: MusicParent?) {} diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt index 0e95243f8..679e573bc 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt @@ -20,6 +20,8 @@ package org.oxycblt.auxio.playback.system import android.content.Context import android.content.Intent import android.graphics.Bitmap +import android.net.Uri +import android.os.Bundle import android.os.SystemClock import android.support.v4.media.MediaDescriptionCompat import android.support.v4.media.MediaMetadataCompat @@ -101,10 +103,15 @@ class MediaSessionComponent( invalidateSessionState() } - override fun onQueueChanged(index: Int, queue: List) { + override fun onQueueChanged(queue: List) { updateQueue(queue) } + override fun onQueueReworked(index: Int, queue: List) { + updateQueue(queue) + invalidateSessionState() + } + override fun onNewPlayback(index: Int, queue: List, parent: MusicParent?) { updateMediaMetadata(playbackManager.song, parent) updateQueue(queue) @@ -118,8 +125,8 @@ class MediaSessionComponent( return } - // We would leave the artist field null if it didn't exist and let downstream consumers - // handle it, but that would break the notification display. + // Note: We would leave the artist field null if it didn't exist and let downstream + // consumers handle it, but that would break the notification display. val title = song.resolveName(context) val artist = song.resolveIndividualArtistName(context) val builder = @@ -180,11 +187,11 @@ class MediaSessionComponent( private fun updateQueue(queue: List) { val queueItems = queue.mapIndexed { i, song -> - // Since we usually have to load many songs into the queue, use the Cover URI + // Since we usually have to load many songs into the queue, use the MediaStore URI // instead of loading a bitmap. val description = MediaDescriptionCompat.Builder() - .setMediaId(song.id.toString()) + .setMediaId("Song:${song.id}") .setTitle(song.resolveName(context)) .setSubtitle(song.resolveIndividualArtistName(context)) .setIconUri(song.album.coverUri) @@ -245,8 +252,8 @@ class MediaSessionComponent( invalidateSessionState() if (!playbackManager.isPlaying) { - // Hack around issue where the position won't update after a seek (but only when it's - // paused). Apparently this can be fixed by re-posting the notification, but not always + // Hack around issue where the position won't update after a seek when paused. + // Apparently this can be fixed by re-posting the notification, but not always // when we invalidate the state (that will cause us to be rate-limited), and also not // always when we seek (that will also cause us to be rate-limited). Someone looked at // this system and said it was well-designed. @@ -256,6 +263,31 @@ class MediaSessionComponent( // --- MEDIASESSION CALLBACKS --- + override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) { + super.onPlayFromMediaId(mediaId, extras) + // STUB: Unimplemented + } + + override fun onPlayFromUri(uri: Uri?, extras: Bundle?) { + super.onPlayFromUri(uri, extras) + // STUB: Unimplemented + } + + override fun onPlayFromSearch(query: String?, extras: Bundle?) { + super.onPlayFromSearch(query, extras) + // STUB: Unimplemented + } + + override fun onAddQueueItem(description: MediaDescriptionCompat?) { + super.onAddQueueItem(description) + // STUB: Unimplemented + } + + override fun onRemoveQueueItem(description: MediaDescriptionCompat?) { + super.onRemoveQueueItem(description) + // STUB: Unimplemented + } + override fun onPlay() { playbackManager.isPlaying = true } 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 31a476df8..2e51cc4d5 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt @@ -27,10 +27,10 @@ import org.oxycblt.auxio.ui.recycler.ArtistViewHolder import org.oxycblt.auxio.ui.recycler.AsyncBackingData 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.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.ui.recycler.MultiAdapter -import org.oxycblt.auxio.ui.recycler.NewHeaderViewHolder import org.oxycblt.auxio.ui.recycler.SimpleItemCallback import org.oxycblt.auxio.ui.recycler.SongViewHolder @@ -43,7 +43,7 @@ class SearchAdapter(listener: MenuItemListener) : MultiAdapter is Album -> AlbumViewHolder.CREATOR is Artist -> ArtistViewHolder.CREATOR is Genre -> GenreViewHolder.CREATOR - is Header -> NewHeaderViewHolder.CREATOR + is Header -> HeaderViewHolder.CREATOR else -> null } @@ -53,7 +53,7 @@ class SearchAdapter(listener: MenuItemListener) : MultiAdapter AlbumViewHolder.CREATOR.viewType -> AlbumViewHolder.CREATOR ArtistViewHolder.CREATOR.viewType -> ArtistViewHolder.CREATOR GenreViewHolder.CREATOR.viewType -> GenreViewHolder.CREATOR - NewHeaderViewHolder.CREATOR.viewType -> NewHeaderViewHolder.CREATOR + HeaderViewHolder.CREATOR.viewType -> HeaderViewHolder.CREATOR else -> null } @@ -68,7 +68,7 @@ class SearchAdapter(listener: MenuItemListener) : MultiAdapter is Album -> (viewHolder as AlbumViewHolder).bind(item, listener) is Artist -> (viewHolder as ArtistViewHolder).bind(item, listener) is Genre -> (viewHolder as GenreViewHolder).bind(item, listener) - is Header -> (viewHolder as NewHeaderViewHolder).bind(item, Unit) + is Header -> (viewHolder as HeaderViewHolder).bind(item, Unit) else -> {} } } @@ -87,7 +87,7 @@ class SearchAdapter(listener: MenuItemListener) : MultiAdapter oldItem is Genre && newItem is Genre -> GenreViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) oldItem is Header && newItem is Header -> - NewHeaderViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) + HeaderViewHolder.DIFFER.areItemsTheSame(oldItem, newItem) else -> false } } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/recycler/ViewHolders.kt b/app/src/main/java/org/oxycblt/auxio/ui/recycler/ViewHolders.kt index cab1dd39a..bd1640443 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/recycler/ViewHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/recycler/ViewHolders.kt @@ -201,7 +201,7 @@ private constructor( * The Shared ViewHolder for a [Header]. * @author OxygenCobalt */ -class NewHeaderViewHolder private constructor(private val binding: ItemHeaderBinding) : +class HeaderViewHolder private constructor(private val binding: ItemHeaderBinding) : BindingViewHolder(binding.root) { override fun bind(item: Header, listener: Unit) { @@ -210,12 +210,12 @@ class NewHeaderViewHolder private constructor(private val binding: ItemHeaderBin companion object { val CREATOR = - object : Creator { + object : Creator { override val viewType: Int get() = IntegerTable.ITEM_TYPE_HEADER override fun create(context: Context) = - NewHeaderViewHolder(ItemHeaderBinding.inflate(context.inflater)) + HeaderViewHolder(ItemHeaderBinding.inflate(context.inflater)) } val DIFFER = diff --git a/app/src/main/res/layout/item_queue_song.xml b/app/src/main/res/layout/item_queue_song.xml index 2f46a1e93..6c999321b 100644 --- a/app/src/main/res/layout/item_queue_song.xml +++ b/app/src/main/res/layout/item_queue_song.xml @@ -27,6 +27,7 @@ android:layout_height="wrap_content"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5492ee937..591f3ed84 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,6 +81,8 @@ Shuffle Queue + Next up + Later Play next Add to queue Added to queue