mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-15 00:42:54 +01:00
playback: keep the queue and player in sync across up-next
A context drag that crosses the up-next block moves the block's anchor in the repository but the old player.move used the combined drop position, leaving the two in different orders. Rebuild the window for context moves that happen while a block exists, in both the in-window and window-offset paths. Also drop the redundant rebuildWindow snapshot parameter, the unused media-item context read-back, and add coverage for shuffled album context, ranged album moves and ranged up-next moves.
This commit is contained in:
@@ -505,6 +505,43 @@ class QueueRepositoryTest {
|
||||
assertEquals(1L, entry.rangeEnd)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingARangedAlbumTrackInUpNextKeepsTheAbsoluteOffsets() =
|
||||
runTest {
|
||||
seedLibrary()
|
||||
db.libraryDao().upsertSongs(
|
||||
listOf(
|
||||
song("s6", "al1", track = 4, album = "First Album"),
|
||||
song("s7", "al1", track = 5, album = "First Album"),
|
||||
song("x1", "al3", track = 1),
|
||||
),
|
||||
)
|
||||
val snapshot = repository.snapshotAfter(listOf(repository.albumEntry(1, "al2")))
|
||||
repository.addUpNext(snapshot, currentPosition = 0, entry = albumRange(1, 4), playNext = false)
|
||||
repository.addUpNext(
|
||||
repository.snapshot(),
|
||||
currentPosition = 0,
|
||||
entry = repository.songEntry(1, "x1"),
|
||||
playNext = false,
|
||||
)
|
||||
assertEquals(listOf("s4", "s2", "s3", "s6", "s7", "x1", "s5"), resolveAll(repository.snapshot()))
|
||||
|
||||
repository.move(repository.snapshot(), from = 4, to = 5)
|
||||
|
||||
var updated = repository.snapshot()
|
||||
assertEquals(listOf("s4", "s2", "s3", "s6", "x1", "s7", "s5"), resolveAll(updated))
|
||||
val moved = updated.locate(5)!!.first
|
||||
assertEquals(QueueKind.Album, moved.kind)
|
||||
assertEquals(4L, moved.rangeStart)
|
||||
assertEquals(4L, moved.rangeEnd)
|
||||
|
||||
repository.move(repository.snapshot(), from = 5, to = 4)
|
||||
|
||||
updated = repository.snapshot()
|
||||
assertEquals(listOf("s4", "s2", "s3", "s6", "s7", "x1", "s5"), resolveAll(updated))
|
||||
assertTrue(updated.isAlbumContext(4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingAPlaylistTrackKeepsItAPinnedSong() =
|
||||
runTest {
|
||||
@@ -897,6 +934,51 @@ class QueueRepositoryTest {
|
||||
assertEquals("First Album", repository.sourceName(entry.kind, entry.sourceId, entry.refId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingWithinARangedAlbumKeepsTheAbsoluteOffsets() =
|
||||
runTest {
|
||||
seedLibrary()
|
||||
db.libraryDao().upsertSongs(
|
||||
listOf(
|
||||
song("s6", "al1", track = 4, album = "First Album"),
|
||||
song("s7", "al1", track = 5, album = "First Album"),
|
||||
),
|
||||
)
|
||||
repository.snapshotAfter(listOf(albumRange(1, 4)))
|
||||
assertEquals(listOf("s2", "s3", "s6", "s7"), resolveAll(repository.snapshot()))
|
||||
|
||||
repository.move(repository.snapshot(), from = 0, to = 2)
|
||||
|
||||
val snapshot = repository.snapshot()
|
||||
assertEquals(listOf("s3", "s6", "s2", "s7"), resolveAll(snapshot))
|
||||
val (entry, _) = snapshot.locate(2)!!
|
||||
assertEquals(QueueKind.Album, entry.kind)
|
||||
assertEquals(1L, entry.rangeStart)
|
||||
assertEquals(1L, entry.rangeEnd)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingBackwardWithinARangedAlbumKeepsTheAbsoluteOffsets() =
|
||||
runTest {
|
||||
seedLibrary()
|
||||
db.libraryDao().upsertSongs(
|
||||
listOf(
|
||||
song("s6", "al1", track = 4, album = "First Album"),
|
||||
song("s7", "al1", track = 5, album = "First Album"),
|
||||
),
|
||||
)
|
||||
repository.snapshotAfter(listOf(albumRange(1, 4)))
|
||||
|
||||
repository.move(repository.snapshot(), from = 3, to = 0)
|
||||
|
||||
val snapshot = repository.snapshot()
|
||||
assertEquals(listOf("s7", "s2", "s3", "s6"), resolveAll(snapshot))
|
||||
val (entry, _) = snapshot.locate(0)!!
|
||||
assertEquals(QueueKind.Album, entry.kind)
|
||||
assertEquals(4L, entry.rangeStart)
|
||||
assertEquals(4L, entry.rangeEnd)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingAnAlbumTrackBackCompactsTheAlbumEntry() =
|
||||
runTest {
|
||||
|
||||
@@ -508,18 +508,26 @@ class PlaybackControllerTest {
|
||||
assertTrue(handle.items.first { it.id == "x1" }.albumContext)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shuffledAlbumTracksKeepAlbumContext() {
|
||||
seedShuffledQueue(seed = 5L)
|
||||
|
||||
assertTrue(handle.items.isNotEmpty())
|
||||
assertTrue(handle.items.all { it.albumContext })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingAnAlbumTrackKeepsItsAlbumGainContext() {
|
||||
seedAlbum(4, sourceId = 1)
|
||||
seedAlbum(60, sourceId = 1)
|
||||
|
||||
controller.playAlbum(1, "al1", 0)
|
||||
await { handle.items.any { it.id == "s1" } }
|
||||
|
||||
runBlocking { controller.move(0, 2) }
|
||||
await { controller.state.value.position == 2L }
|
||||
runBlocking { controller.move(0, 40) }
|
||||
await { controller.state.value.position == 40L }
|
||||
|
||||
assertTrue(handle.items.first { it.id == "s1" }.albumContext)
|
||||
val (entry, _) = runBlocking { queues.snapshot().locate(2)!! }
|
||||
val (entry, _) = runBlocking { queues.snapshot().locate(40)!! }
|
||||
assertEquals(QueueKind.Album, entry.kind)
|
||||
assertEquals("al1", entry.refId)
|
||||
}
|
||||
@@ -540,6 +548,35 @@ class PlaybackControllerTest {
|
||||
assertTrue(handle.items.first { it.id == "s2" }.albumContext)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingAContextTrackAcrossUpNextKeepsPlayerAndQueueInSync() {
|
||||
seedAlbum(3, sourceId = 1)
|
||||
seedSong("x1", "al2")
|
||||
|
||||
controller.playAlbum(1, "al1", 0)
|
||||
await {
|
||||
controller.state.value.item
|
||||
?.id == "s1"
|
||||
}
|
||||
controller.addToQueue(1, QueueKind.Song, "x1")
|
||||
await { handle.items.any { it.id == "x1" } }
|
||||
|
||||
runBlocking { controller.move(0, 3) }
|
||||
await { controller.state.value.position == 2L }
|
||||
|
||||
val expected =
|
||||
runBlocking {
|
||||
val snapshot = queues.snapshot()
|
||||
(0 until snapshot.size).mapNotNull { queues.itemAt(snapshot, it)?.song?.id }
|
||||
}
|
||||
assertEquals(expected, handle.items.map { it.id })
|
||||
assertEquals(
|
||||
"s1",
|
||||
controller.state.value.item
|
||||
?.id,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun tappingAContextTrackWhileAQueuedTrackPlaysKeepsTheQueue() {
|
||||
seedAlbum(3, sourceId = 1)
|
||||
|
||||
Reference in New Issue
Block a user