address review: renumber moves from the window start and version the length cache

This commit is contained in:
austinried
2026-10-04 00:29:59 +00:00
parent 8ae5ba5e4b
commit 8ba0aa5192
3 changed files with 34 additions and 7 deletions
@@ -21,6 +21,7 @@ const val QUEUE_CHUNK = 60
private const val LENGTH_CACHE_LIMIT = 512
private data class EntryLengthKey(
val version: Long,
val sourceId: Long,
val kind: QueueKind,
val refId: String,
@@ -147,7 +148,7 @@ class QueueRepository(
val loaded =
db.useReaderConnection { transactor ->
transactor.deferredTransaction {
val entries = dao.entries().map { ResolvedQueueEntry(it, lengthOf(it)) }
val entries = dao.entries().map { ResolvedQueueEntry(it, lengthOf(it, version)) }
val row = dao.cursor()
val shuffled = row?.shuffleEnabled == true
val order = if (shuffled) loadShuffleOrder(row.shuffleSeed, entries.sumOf { it.length }) else null
@@ -386,8 +387,11 @@ class QueueRepository(
}
}
private suspend fun lengthOf(entry: QueueEntry): Long {
val key = entry.lengthKey()
private suspend fun lengthOf(
entry: QueueEntry,
version: Long,
): Long {
val key = entry.lengthKey(version)
lengthCache[key]?.let { return it }
val length = entry.resolvedLength()
if (lengthCache.size >= LENGTH_CACHE_LIMIT) lengthCache.clear()
@@ -395,8 +399,9 @@ class QueueRepository(
return length
}
private fun QueueEntry.lengthKey() =
private fun QueueEntry.lengthKey(version: Long) =
EntryLengthKey(
version = version,
sourceId = sourceId,
kind = kind,
refId = refId,
@@ -184,7 +184,7 @@ class QueueViewModel(
viewModelScope.launch {
playbackController.move(from, to)
mutex.withLock {
val base = rows.firstOrNull()?.position ?: return@withLock
val base = rows.minOfOrNull { it.position } ?: return@withLock
// The loaded order already reflects the move, so only the positions need updating.
val updated =
rows.mapIndexed { index, row ->
@@ -199,8 +199,30 @@ class QueueViewModelTest {
viewModel.rows[13]
.song.song.id,
)
assertEquals(QUEUE_WINDOW_ROWS, viewModel.rows.size)
assertContiguous()
assertEquals((220L..399L).toList(), viewModel.rows.map { it.position })
}
@Test
fun movingTheTopRowDownRenumbersFromTheWindowStart() {
runBlocking { seedSongs(400) }
controller.playAlbum(1, "al1", 100)
await { controller.state.value.position == 100L }
viewModel.open()
await { viewModel.ready }
extendToEnd()
assertEquals((220L..399L).toList(), viewModel.rows.map { it.position })
val from = viewModel.rows.first().position
viewModel.reorder(0, 5)
val to = dropTarget(viewModel.rows, index = 5, from = from)
viewModel.move(from, to)
await {
viewModel.rows.firstOrNull()?.position == 220L &&
viewModel.rows.lastOrNull()?.position == 399L
}
assertEquals((220L..399L).toList(), viewModel.rows.map { it.position })
}
@Test