diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f422c3a12..67ef8206c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,7 +7,6 @@
= mUserQueue.value!!.size || to < 0) return false
+ queueAdapter.moveItems(adapterFrom, adapterTo)
+
playbackManager.moveUserQueueItems(from, to)
} else {
// Ignore invalid movements to out of bounds or header positions
@@ -205,6 +212,8 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
if (to <= mIndex.value!!) return false
}
+ queueAdapter.moveItems(adapterFrom, adapterTo)
+
playbackManager.moveQueueItems(from, to)
}
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 1ad4caf98..e5c3cce94 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
@@ -5,8 +5,8 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewGroup
+import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.ItemTouchHelper
-import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
import org.oxycblt.auxio.music.BaseModel
@@ -16,11 +16,24 @@ import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder
+/**
+ * The single adapter for both the Next Queue and the User Queue.
+ * - [submitList] is for the plain async diff calculations, use this if you
+ * have no idea what the differences are between the old data & the new data
+ * - [removeItem] and [moveItems] are used by [org.oxycblt.auxio.playback.PlaybackViewModel]
+ * so that this adapter doesn't flip-out when items are moved (Which happens with [AsyncListDiffer])
+ * @author OxygenCobalt
+ */
class QueueAdapter(
- val touchHelper: ItemTouchHelper
-) : ListAdapter(DiffCallback()) {
+ private val touchHelper: ItemTouchHelper
+) : RecyclerView.Adapter() {
+ private var data = mutableListOf()
+ private var listDiffer = AsyncListDiffer(this, DiffCallback())
+
+ override fun getItemCount(): Int = data.size
+
override fun getItemViewType(position: Int): Int {
- val item = getItem(position)
+ val item = data[position]
return if (item is Header)
HeaderViewHolder.ITEM_TYPE
@@ -39,7 +52,7 @@ class QueueAdapter(
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- when (val item = getItem(position)) {
+ when (val item = data[position]) {
is Song -> (holder as ViewHolder).bind(item)
is Header -> (holder as HeaderViewHolder).bind(item)
@@ -49,6 +62,27 @@ class QueueAdapter(
}
}
+ fun submitList(newData: MutableList) {
+ if (data != newData) {
+ data = newData
+
+ listDiffer.submitList(newData)
+ }
+ }
+
+ fun moveItems(adapterFrom: Int, adapterTo: Int) {
+ val item = data.removeAt(adapterFrom)
+ data.add(adapterTo, item)
+
+ notifyItemMoved(adapterFrom, adapterTo)
+ }
+
+ fun removeItem(adapterIndex: Int) {
+ data.removeAt(adapterIndex)
+
+ notifyItemRemoved(adapterIndex)
+ }
+
// Generic ViewHolder for a queue item
inner class ViewHolder(
private val binding: ItemQueueSongBinding,
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 97d81f20d..4cbb0984b 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
@@ -10,6 +10,8 @@ import kotlin.math.sign
// The drag callback used for the Queue RecyclerView.
class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() {
+ private lateinit var queueAdapter: QueueAdapter
+
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
@@ -51,11 +53,15 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
- return playbackModel.moveQueueItems(viewHolder.adapterPosition, target.adapterPosition)
+ return playbackModel.moveQueueItems(viewHolder.adapterPosition, target.adapterPosition, queueAdapter)
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
- playbackModel.removeQueueItem(viewHolder.adapterPosition)
+ playbackModel.removeQueueItem(viewHolder.adapterPosition, queueAdapter)
+ }
+
+ fun addQueueAdapter(adapter: QueueAdapter) {
+ queueAdapter = adapter
}
companion object {
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 be511894c..4681d1145 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
@@ -8,7 +8,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper
-import androidx.recyclerview.widget.LinearLayoutManager
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentQueueBinding
import org.oxycblt.auxio.music.BaseModel
@@ -27,8 +26,10 @@ class QueueFragment : Fragment() {
): View? {
val binding = FragmentQueueBinding.inflate(inflater)
- val helper = ItemTouchHelper(QueueDragCallback(playbackModel))
+ val callback = QueueDragCallback(playbackModel)
+ val helper = ItemTouchHelper(callback)
val queueAdapter = QueueAdapter(helper)
+ callback.addQueueAdapter(queueAdapter)
// --- UI SETUP ---
@@ -50,9 +51,7 @@ class QueueFragment : Fragment() {
findNavController().navigateUp()
}
- queueAdapter.submitList(createQueueDisplay()) {
- scrollRecyclerIfNeeded(binding)
- }
+ queueAdapter.submitList(createQueueData())
}
playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) {
@@ -60,15 +59,13 @@ class QueueFragment : Fragment() {
findNavController().navigateUp()
}
- queueAdapter.submitList(createQueueDisplay()) {
- scrollRecyclerIfNeeded(binding)
- }
+ queueAdapter.submitList(createQueueData())
}
return binding.root
}
- private fun createQueueDisplay(): MutableList {
+ private fun createQueueData(): MutableList {
val queue = mutableListOf()
if (playbackModel.userQueue.value!!.isNotEmpty()) {
@@ -93,12 +90,4 @@ class QueueFragment : Fragment() {
return queue
}
-
- private fun scrollRecyclerIfNeeded(binding: FragmentQueueBinding) {
- if ((binding.queueRecycler.layoutManager as LinearLayoutManager)
- .findFirstVisibleItemPosition() < 1
- ) {
- binding.queueRecycler.scrollToPosition(0)
- }
- }
}
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 7c94209fc..208503330 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
@@ -13,7 +13,8 @@ import kotlin.random.Random
/**
* Master class for the playback state. This should ***not*** be used outside of the playback module.
* - 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].
+ * - If you want to use the playback state with the ExoPlayer instance or system-side things,
+ * use [org.oxycblt.auxio.playback.PlaybackService].
*
* All instantiation should be done with [PlaybackStateManager.from()].
* @author OxygenCobalt
@@ -120,7 +121,7 @@ class PlaybackStateManager private constructor() {
PlaybackMode.ALL_SONGS -> null
PlaybackMode.IN_ARTIST -> song.album.artist
PlaybackMode.IN_ALBUM -> song.album
- PlaybackMode.IN_GENRE -> error("what")
+ PlaybackMode.IN_GENRE -> song.album.artist.genres[0]
}
mMode = mode
@@ -129,7 +130,7 @@ class PlaybackStateManager private constructor() {
PlaybackMode.ALL_SONGS -> musicStore.songs.toMutableList()
PlaybackMode.IN_ARTIST -> song.album.artist.songs
PlaybackMode.IN_ALBUM -> song.album.songs
- PlaybackMode.IN_GENRE -> error("what")
+ PlaybackMode.IN_GENRE -> song.album.artist.genres[0].songs
}
resetLoopMode()
diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt b/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt
index db2a586df..f04767d61 100644
--- a/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt
+++ b/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt
@@ -6,10 +6,10 @@ import org.oxycblt.auxio.music.BaseModel
// Base Diff callback
class DiffCallback : DiffUtil.ItemCallback() {
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
- return oldItem.id == newItem.id
+ return oldItem == newItem
}
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
- return oldItem == newItem
+ return oldItem.id == newItem.id
}
}
diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
index e50408be5..597616ae3 100644
--- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
+++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt
@@ -39,6 +39,10 @@ fun ImageButton.disable(context: Context) {
}
}
+fun String.createToast(context: Context) {
+ Toast.makeText(context, this, Toast.LENGTH_SHORT).show()
+}
+
// Apply a custom vertical divider
fun RecyclerView.applyDivider() {
val div = DividerItemDecoration(
@@ -117,19 +121,7 @@ private fun doUserQueueAdd(context: Context, song: Song, playbackModel: Playback
// 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)
+ 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()
- }
+ context.getString(R.string.label_queue_added).createToast(context)
}
diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
index 2a9095709..0afa0c283 100644
--- a/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
+++ b/app/src/main/java/org/oxycblt/auxio/ui/ThemeUtils.kt
@@ -19,7 +19,7 @@ private val ACCENTS = listOf(
Pair(R.color.deep_purple, R.style.Theme_DeepPurple), // 3
Pair(R.color.indigo, R.style.Theme_Indigo), // 4
Pair(R.color.blue, R.style.Theme_Blue), // 5
- Pair(R.color.light_blue, R.style.Theme_Blue), // 6
+ Pair(R.color.light_blue, R.style.Theme_LightBlue), // 6
Pair(R.color.cyan, R.style.Theme_Cyan), // 7
Pair(R.color.teal, R.style.Theme_Teal), // 8
Pair(R.color.green, R.style.Theme_Green), // 9
diff --git a/app/src/main/res/drawable/ui_seekbar_indicator.xml b/app/src/main/res/drawable/ui_seekbar_indicator.xml
deleted file mode 100644
index a6a040324..000000000
--- a/app/src/main/res/drawable/ui_seekbar_indicator.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- -
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_header.xml b/app/src/main/res/layout/item_header.xml
index 56b5df336..a40341f26 100644
--- a/app/src/main/res/layout/item_header.xml
+++ b/app/src/main/res/layout/item_header.xml
@@ -1,7 +1,6 @@
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5c521aad6..e8dcdd985 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -61,7 +61,6 @@
Unknown Genre
Unknown Artist
Unknown Album
- Unknown Song
No Date
diff --git a/build.gradle b/build.gradle
index 3c34f805b..b6795aad6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0"