Fix Play Next ignoring shuffle order (#1222)

This commit is contained in:
Sam Mingo authored and birdbird committed 2026-10-05 15:58:05 +00:00
1 parent bd39b61f02
commit 37b6ad2271
2 files changed
+48 -2

No files matched your search

+3
View File
@@ -29,6 +29,9 @@ This is a list of requirements that the internal playback is built around.
play order and starts at its first item while shuffle is enabled.
- Adding "next" during shuffle puts all inserted items immediately after the current item in their
supplied order; Media3's randomly assigned insertion positions must not leak into the UI order.
Implementation: `QueueAwarePlayer.addMediaItems` detects `shuffleModeEnabled && index ==
currentMediaItemIndex + 1` and rewrites the shuffle order via `ShuffleOrderCoordinator.insertNext`
to splice the new items at `currentShufflePos + 1`.
- Reordering a shuffled queue changes play order without accidentally treating a play-order row as
a canonical Media3 index.
- Queue, current item/index/position, repeat mode, shuffle flag, and exact shuffle order survive
@@ -1,6 +1,7 @@
package org.moire.ultrasonic.service
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -103,10 +104,52 @@ class PlaybackQueueActionsTest {
verify(playback, never()).play()
}
private fun playback(shuffleEnabled: Boolean): PlaybackRepository {
@Test
fun `play next without shuffle inserts immediately after current item`() = runTest {
val playback = playback(shuffleEnabled = false, currentIndex = 2, queueSize = 5)
PlaybackQueueActions(playback).add(
tracks = emptyList(),
insertionMode = QueueInsertionMode.AFTER_CURRENT,
autoPlay = false
)
// insertAt = currentMediaItemIndex + 1 = 3
verify(playback).addMediaItems(3, emptyList())
}
@Test
fun `play next with shuffle inserts at correct index for QueueAwarePlayer to reorder`() =
runTest {
val playback = playback(shuffleEnabled = true, currentIndex = 1, queueSize = 4)
PlaybackQueueActions(playback).add(
tracks = emptyList(),
insertionMode = QueueInsertionMode.AFTER_CURRENT,
autoPlay = false
)
// insertAt = currentMediaItemIndex + 1 = 2; QueueAwarePlayer handles shuffle order
verify(playback).addMediaItems(2, emptyList())
}
private fun playback(
shuffleEnabled: Boolean,
currentIndex: Int = C.INDEX_UNSET,
queueSize: Int = 0
): PlaybackRepository {
val playback = mock<PlaybackRepository>()
val entries = (0 until queueSize).map { i ->
PlaybackQueueEntry(mediaItemIndex = i, mediaItem = MediaItem.EMPTY)
}
whenever(playback.snapshot).thenReturn(
MutableStateFlow(PlaybackSnapshot(shuffleModeEnabled = shuffleEnabled))
MutableStateFlow(
PlaybackSnapshot(
shuffleModeEnabled = shuffleEnabled,
currentMediaItemIndex = currentIndex,
queueInPlayOrder = entries
)
)
)
return playback
}