Prevent the addition of duplicate queue items
Band-aid over a bug with DiffCallback that causes weird behavior with duplicate queue items by disallowing the addition of queue items if theyre already allowed.
This commit is contained in:
parent
604145fb69
commit
2aa630948b
14 changed files with 59 additions and 43 deletions
|
@ -3,7 +3,6 @@ package org.oxycblt.auxio.music
|
|||
import android.net.Uri
|
||||
|
||||
// --- MUSIC MODELS ---
|
||||
// FIXME: Remove parent/child references so that they can be parcelable?
|
||||
|
||||
// The base model for all music
|
||||
// This is used in a lot of general functions in order to have generic utilities
|
||||
|
|
|
@ -92,6 +92,9 @@ class MusicStore private constructor() {
|
|||
@Volatile
|
||||
private var INSTANCE: MusicStore? = null
|
||||
|
||||
/**
|
||||
* Get/Instantiate the single instance of [MusicStore].
|
||||
*/
|
||||
fun getInstance(): MusicStore {
|
||||
val currentInstance = INSTANCE
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ private val ID3_GENRES = arrayOf(
|
|||
"Anime", "JPop", "Synthpop"
|
||||
)
|
||||
|
||||
const val PAREN_FILTER = "()"
|
||||
private const val PAREN_FILTER = "()"
|
||||
|
||||
// --- EXTENSION FUNCTIONS ---
|
||||
|
||||
|
|
|
@ -22,17 +22,16 @@ class QueueAdapter(
|
|||
override fun getItemViewType(position: Int): Int {
|
||||
val item = getItem(position)
|
||||
|
||||
if (item is Header) {
|
||||
return HeaderViewHolder.ITEM_TYPE
|
||||
} else {
|
||||
return QUEUE_ITEM_VIEW_TYPE
|
||||
}
|
||||
return if (item is Header)
|
||||
HeaderViewHolder.ITEM_TYPE
|
||||
else
|
||||
QUEUE_ITEM_TYPE
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
HeaderViewHolder.ITEM_TYPE -> HeaderViewHolder.from(parent.context)
|
||||
QUEUE_ITEM_VIEW_TYPE -> ViewHolder(
|
||||
QUEUE_ITEM_TYPE -> ViewHolder(
|
||||
ItemQueueSongBinding.inflate(LayoutInflater.from(parent.context))
|
||||
)
|
||||
else -> error("Someone messed with the ViewHolder item types. Tell OxygenCobalt.")
|
||||
|
@ -76,6 +75,6 @@ class QueueAdapter(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val QUEUE_ITEM_VIEW_TYPE = 0xA030
|
||||
const val QUEUE_ITEM_TYPE = 0xA015
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc
|
|||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
): Int {
|
||||
// Only allow dragging/swiping with the queue item ViewHolder, not the header items.
|
||||
// Only allow dragging/swiping with the queue item ViewHolder, not the headers.
|
||||
return if (viewHolder is QueueAdapter.ViewHolder) {
|
||||
makeFlag(
|
||||
ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP or ItemTouchHelper.DOWN
|
||||
|
|
|
@ -43,6 +43,8 @@ class QueueFragment : Fragment() {
|
|||
helper.attachToRecyclerView(this)
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
playbackModel.userQueue.observe(viewLifecycleOwner) {
|
||||
if (it.isEmpty() && playbackModel.nextItemsInQueue.value!!.isEmpty()) {
|
||||
findNavController().navigateUp()
|
||||
|
|
|
@ -12,7 +12,7 @@ import kotlin.random.Random
|
|||
|
||||
/**
|
||||
* Master class for the playback state. This should ***not*** be used outside of the playback module.
|
||||
* - If you want to show the playback state in the UI, use [org.oxycblt.auxio.playback.PlaybackViewModel].
|
||||
* - If you want to use the playback state in the UI, use [org.oxycblt.auxio.playback.PlaybackViewModel].
|
||||
* - If you want to add to the system aspects or the exoplayer instance, use [org.oxycblt.auxio.playback.PlaybackService].
|
||||
*
|
||||
* All instantiation should be done with [PlaybackStateManager.from()].
|
||||
|
@ -301,6 +301,8 @@ class PlaybackStateManager private constructor() {
|
|||
|
||||
mUserQueue.removeAt(index)
|
||||
|
||||
Log.d(this::class.simpleName, mUserQueue.toString())
|
||||
|
||||
forceUserQueueUpdate()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.oxycblt.auxio.recycler
|
||||
|
||||
// TODO: Swap these temp values for actual constants
|
||||
enum class ShowMode {
|
||||
SHOW_GENRES, SHOW_ARTISTS, SHOW_ALBUMS, SHOW_SONGS;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class GenreViewHolder private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 10
|
||||
const val ITEM_TYPE = 0xA010
|
||||
|
||||
fun from(context: Context, doOnClick: (Genre) -> Unit): GenreViewHolder {
|
||||
return GenreViewHolder(
|
||||
|
@ -50,7 +50,7 @@ class ArtistViewHolder private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 11
|
||||
const val ITEM_TYPE = 0xA011
|
||||
|
||||
fun from(context: Context, doOnClick: (Artist) -> Unit): ArtistViewHolder {
|
||||
return ArtistViewHolder(
|
||||
|
@ -72,7 +72,7 @@ class AlbumViewHolder private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 12
|
||||
const val ITEM_TYPE = 0xA012
|
||||
|
||||
fun from(context: Context, doOnClick: (data: Album) -> Unit): AlbumViewHolder {
|
||||
return AlbumViewHolder(
|
||||
|
@ -99,7 +99,7 @@ class SongViewHolder private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 13
|
||||
const val ITEM_TYPE = 0xA013
|
||||
|
||||
fun from(
|
||||
context: Context,
|
||||
|
@ -123,7 +123,7 @@ class HeaderViewHolder(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 14
|
||||
const val ITEM_TYPE = 0xA014
|
||||
|
||||
fun from(context: Context): HeaderViewHolder {
|
||||
return HeaderViewHolder(
|
||||
|
|
|
@ -60,13 +60,7 @@ fun PopupMenu.setupSongActions(song: Song, context: Context, playbackModel: Play
|
|||
setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
R.id.action_queue_add -> {
|
||||
playbackModel.addToUserQueue(song)
|
||||
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.label_queue_added),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
doUserQueueAdd(context, song, playbackModel)
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -97,13 +91,7 @@ fun PopupMenu.setupAlbumSongActions(
|
|||
setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
R.id.action_queue_add -> {
|
||||
playbackModel.addToUserQueue(song)
|
||||
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.label_queue_added),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
doUserQueueAdd(context, song, playbackModel)
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -113,8 +101,35 @@ fun PopupMenu.setupAlbumSongActions(
|
|||
true
|
||||
}
|
||||
|
||||
R.id.action_play_artist -> {
|
||||
playbackModel.playSong(song, PlaybackMode.IN_ARTIST)
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
private fun doUserQueueAdd(context: Context, song: Song, playbackModel: PlaybackViewModel) {
|
||||
// If the song was already added to the user queue, then don't add it again.
|
||||
// This is just to prevent a bug with DiffCallback that creates strange
|
||||
// behavior when duplicate user queue items are added.
|
||||
// FIXME: Fix the duplicate item DiffCallback issue
|
||||
if (!playbackModel.userQueue.value!!.contains(song)) {
|
||||
playbackModel.addToUserQueue(song)
|
||||
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.label_queue_added),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
} else {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.label_queue_already_added),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_margin="@dimen/margin_mid_large"
|
||||
android:contentDescription="@{@string/description_album_cover(song.name)}"
|
||||
android:outlineProvider="bounds"
|
||||
android:elevation="4dp"
|
||||
app:coverArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_song"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".playback.queue.QueueFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -34,15 +35,5 @@
|
|||
tools:layout_editor_absoluteX="0dp"
|
||||
tools:listitem="@layout/item_song" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_nothing_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/label_empty_queue"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
|
@ -8,4 +8,8 @@
|
|||
android:id="@+id/action_go_artist"
|
||||
android:title="@string/label_go_artist"
|
||||
android:icon="@drawable/ic_artist" />
|
||||
<item
|
||||
android:id="@+id/action_play_artist"
|
||||
android:title="@string/label_play_artist"
|
||||
android:icon="@drawable/ic_artist" />
|
||||
</menu>
|
|
@ -32,7 +32,7 @@
|
|||
<string name="label_queue_add">Add to queue</string>
|
||||
<string name="label_queue_added">Added to queue</string>
|
||||
<string name="label_next_user_queue">Next in Queue</string>
|
||||
<string name="label_empty_queue">Nothing here</string>
|
||||
<string name="label_queue_already_added">Already in queue!</string>
|
||||
<string name="label_notification_playback">Music Playback</string>
|
||||
<string name="label_service_playback">The music playback service for Auxio.</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue