diff --git a/app/src/main/kotlin/com/subtracks/playback/PlaybackController.kt b/app/src/main/kotlin/com/subtracks/playback/PlaybackController.kt index b57b6653..4f228c17 100644 --- a/app/src/main/kotlin/com/subtracks/playback/PlaybackController.kt +++ b/app/src/main/kotlin/com/subtracks/playback/PlaybackController.kt @@ -337,6 +337,7 @@ class PlaybackController( if (wasUpNext) queueRepository.combinedIndexOf(updated, it) else queueRepository.combinedContextIndexOf(updated, it) } ?: (if (position < current) current - 1 else current) ).coerceIn(0, updated.size - 1) + lastPosition = target lastEdit = if (removed == null) { ReloadUndo(entries, cursor, snapshot.shuffleOrder, upNext, snapshot.upNextAnchor) @@ -390,6 +391,7 @@ class PlaybackController( if (!queueRepository.move(snapshot, from, to)) return@withLock this.snapshot = readSnapshot() val target = movedCursor(current, from, to) + lastPosition = target windowJob?.cancel() val fromInWindow = from in windowStart..windowEnd val toInWindow = to in windowStart..windowEnd @@ -447,6 +449,7 @@ class PlaybackController( return@withLock } val target = undo.cursor.coerceIn(0, restored.size - 1) + lastPosition = target val restoredId = queueRepository.itemAt(restored, target)?.song?.id windowJob?.cancel() val canMirror = @@ -951,6 +954,7 @@ class PlaybackController( } finally { updating = false } + lastPosition = target } private fun rebuildWindow( diff --git a/app/src/test/kotlin/com/subtracks/playback/PlaybackControllerTest.kt b/app/src/test/kotlin/com/subtracks/playback/PlaybackControllerTest.kt index 9b63a348..e7a9c08a 100644 --- a/app/src/test/kotlin/com/subtracks/playback/PlaybackControllerTest.kt +++ b/app/src/test/kotlin/com/subtracks/playback/PlaybackControllerTest.kt @@ -733,6 +733,96 @@ class PlaybackControllerTest { eager.close() } + @Test + fun movingAQueuedTrackFromAnotherAlbumBeforeTheCurrentDoesNotConsumeIt() { + seedAlbum(3, sourceId = 1) + seedSong("b1", "al2") + seedSong("b2", "al2") + seedSong("c1", "al3") + val eagerHandle = FakePlayerHandle() + val inline = + object : kotlinx.coroutines.CoroutineDispatcher() { + override fun dispatch( + context: kotlin.coroutines.CoroutineContext, + block: Runnable, + ) = block.run() + } + val eager = PlaybackController(sources, queues, FakePlayerConnection(eagerHandle), dispatcher = inline) + + eager.playAlbum(1, "al1", 0) + await { + eager.state.value.item + ?.id == "s1" + } + eager.addToQueue(1, QueueKind.Album, "al2") + eager.addToQueue(1, QueueKind.Song, "c1") + await { runBlocking { eager.upcomingItem()?.id } == "b1" } + + eager.playAt(2) + await { + eager.state.value.item + ?.id == "b2" + } + + runBlocking { eager.move(3, 2) } + Thread.sleep(300) + + assertEquals( + "b2", + eager.state.value.item + ?.id, + ) + assertEquals(3L, runBlocking { queues.snapshot().upNextSize }) + eager.close() + } + + @Test + fun movingAQueuedTrackBeforeTheCurrentConsumesTheRightTrackOnSkip() { + seedAlbum(3, sourceId = 1) + seedSong("b1", "al2") + seedSong("b2", "al2") + seedSong("c1", "al3") + val eagerHandle = FakePlayerHandle() + val inline = + object : kotlinx.coroutines.CoroutineDispatcher() { + override fun dispatch( + context: kotlin.coroutines.CoroutineContext, + block: Runnable, + ) = block.run() + } + val eager = PlaybackController(sources, queues, FakePlayerConnection(eagerHandle), dispatcher = inline) + + eager.playAlbum(1, "al1", 0) + await { + eager.state.value.item + ?.id == "s1" + } + eager.addToQueue(1, QueueKind.Album, "al2") + eager.addToQueue(1, QueueKind.Song, "c1") + await { runBlocking { eager.upcomingItem()?.id } == "b1" } + eager.playAt(1) + await { + eager.state.value.item + ?.id == "b1" + } + + runBlocking { eager.move(3, 1) } + await { + eager.state.value.item + ?.id == "b1" + } + + eagerHandle.advanceTo(eagerHandle.currentIndex + 1) + await { + eager.state.value.item + ?.id == "b2" + } + + val queued = runBlocking { queues.snapshot().upNext.map { it.entry.refId } } + assertTrue("c1" in queued) + eager.close() + } + @Test fun nextFollowsTheReorderedQueue() { seedAlbum(3, sourceId = 1)