keep the playing context and window across an offline toggle

This commit is contained in:
austinried
2026-10-04 00:30:04 +00:00
parent 813ca00fba
commit 8a90635666
2 changed files with 72 additions and 2 deletions
@@ -146,6 +146,7 @@ class PlaybackController(
private val offline: Boolean get() = sourceRepository.offline.value
private var windowPositions = LongArray(0)
private var windowFiltered = false
private var contextOverride: QueueContext? = null
init {
scope.launch {
@@ -154,7 +155,7 @@ class PlaybackController(
}
}
scope.launch {
sourceRepository.offline.drop(1).collect { reloadForOffline() }
sourceRepository.offline.collect { reloadForOffline() }
}
scope.launch {
sourceRepository.quality.drop(1).collect {
@@ -243,6 +244,7 @@ class PlaybackController(
disableShuffle: Boolean = false,
) {
if (!offline) {
contextOverride = null
play(listOf(entry), start, disableShuffle)
return
}
@@ -252,12 +254,14 @@ class PlaybackController(
showMessage("Nothing downloaded for offline playback")
return@launch
}
contextOverride = QueueContext(entry.kind, entry.sourceId, entry.refId)
play(entries, start, disableShuffle = true)
}
}
private fun shuffleContext(entry: QueueEntry) {
if (!offline) {
contextOverride = null
shufflePlay(listOf(entry))
return
}
@@ -267,6 +271,7 @@ class PlaybackController(
showMessage("Nothing downloaded for offline playback")
return@launch
}
contextOverride = QueueContext(entry.kind, entry.sourceId, entry.refId)
shufflePlay(entries)
}
}
@@ -1019,6 +1024,7 @@ class PlaybackController(
windowEnd = -1
windowPositions = LongArray(0)
windowFiltered = false
contextOverride = null
lastPosition = null
lastEdit = null
player?.run {
@@ -1387,6 +1393,7 @@ class PlaybackController(
}
private fun contextAt(position: Long?): QueueContext? {
contextOverride?.let { return it }
val snapshot = snapshot ?: return null
val play = position?.let { snapshot.anchorContextPlay(it) } ?: return null
val entry = snapshot.locateContext(play)?.first ?: return null
@@ -73,7 +73,7 @@ class PlaybackControllerTest {
networkMode = MutableStateFlow(NetworkMode.Wifi)
sources = SourceRepository(db, OkHttpClient(), prefs, ArtworkStore(File(context.cacheDir, "art")), networkMode = networkMode)
queues = QueueRepository(db)
downloadsDir = File(context.cacheDir, "downloads")
downloadsDir = File(context.cacheDir, "downloads-${System.nanoTime()}")
downloads =
DownloadRepository(
db,
@@ -2495,6 +2495,69 @@ class PlaybackControllerTest {
)
}
@Test
fun offlinePlayAlbumKeepsTheAlbumAsThePlayingContext() {
seedAlbum(4, sourceId = 1)
markDownloaded(1, "s1")
markDownloaded(1, "s3")
setOffline()
controller.playAlbum(1, "al1", 0)
await {
controller.state.value.context
?.kind == QueueKind.Album
}
assertEquals(
QueueKind.Album,
controller.state.value.context
?.kind,
)
assertEquals(
"al1",
controller.state.value.context
?.refId,
)
}
@Test
fun offlineUpNextPlaysAndIsConsumed() {
seedAlbum(8, sourceId = 1)
seedSong("x1", "al2")
(1..8).filter { it != 2 }.forEach { markDownloaded(1, "s$it") }
markDownloaded(1, "x1")
controller.playAlbum(1, "al1", 3)
await {
controller.state.value.item
?.id == "s4"
}
setOffline()
await { handle.items.map { it.id } == listOf("s1", "s3", "s4", "s5", "s6", "s7", "s8") }
controller.addToQueue(1, QueueKind.Song, "x1")
await { runBlocking { queues.snapshot().upNextSize } == 1L }
controller.next()
await {
controller.state.value.item
?.id == "x1"
}
controller.next()
await { runBlocking { queues.snapshot().upNextSize } == 0L }
await {
controller.state.value.item
?.id == "s5"
}
assertEquals(
"s5",
controller.state.value.item
?.id,
)
}
@Test
fun offlinePlayAlbumBuildsADownloadedOnlyQueue() {
seedAlbum(4, sourceId = 1)