keep the artist sort index and bound the offline queue-view scan

This commit is contained in:
austinried
2026-10-04 00:30:05 +00:00
parent 0dff769d14
commit ae4c500ae1
3 changed files with 22 additions and 15 deletions
@@ -82,8 +82,8 @@ internal const val ARTISTS_SELECT =
internal const val ARTIST_ORDER_BY_NAME = "name COLLATE NOCASE, id"
internal const val ARTIST_ORDER_BY_NAME_REVERSED = "name COLLATE NOCASE DESC, id DESC"
internal const val ARTIST_ORDER_BY_ALBUM_COUNT = "albumCount DESC, name COLLATE NOCASE, id"
internal const val ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED = "albumCount ASC, name COLLATE NOCASE DESC, id DESC"
internal const val ARTIST_ORDER_BY_ALBUM_COUNT = "artists.albumCount DESC, name COLLATE NOCASE, id"
internal const val ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED = "artists.albumCount ASC, name COLLATE NOCASE DESC, id DESC"
internal const val ARTIST_ORDER_BY_STARRED = "starred DESC NULLS LAST, name COLLATE NOCASE, id"
internal const val ARTIST_ORDER_BY_STARRED_REVERSED = "starred ASC NULLS LAST, name COLLATE NOCASE DESC, id DESC"
@@ -74,6 +74,12 @@ private const val POSITION_TIMEOUT_MS = 1_000L
internal const val QUEUE_WINDOW_ROWS = QUEUE_CHUNK * 3
// Offline the view hides non-downloaded rows, so resolving a contiguous position range can span far
// more than it shows. Cap the positions resolved per load (and per reconcile) so a sparse large
// playlist cannot make the view resolve the whole queue; online every position is shown, so the cap
// is never reached.
private const val MAX_SCAN_POSITIONS = QUEUE_WINDOW_ROWS * 4
data class QueueRow(
val id: Long,
val position: Long,
@@ -158,7 +164,8 @@ class QueueViewModel(
return
}
val start = (rows.minOfOrNull { it.position } ?: 0L).coerceIn(0, snapshot.size - 1)
val end = (rows.maxOfOrNull { it.position } ?: (start + QUEUE_CHUNK - 1)).coerceIn(start, snapshot.size - 1)
val rawEnd = (rows.maxOfOrNull { it.position } ?: (start + QUEUE_CHUNK - 1)).coerceIn(start, snapshot.size - 1)
val end = rawEnd.coerceAtMost(start + MAX_SCAN_POSITIONS - 1)
val loaded = queueRepository.range(snapshot, start, end).filter(::visible)
val reused = reusedIds()
val updated = loaded.map { rowFor(it, reused) }
@@ -180,9 +187,11 @@ class QueueViewModel(
val snapshot = queueRepository.snapshot()
val collected = mutableListOf<QueueWindowItem>()
var end = first - 1
while (end >= 0L && collected.size < QUEUE_CHUNK) {
var scanned = 0L
while (end >= 0L && collected.size < QUEUE_CHUNK && scanned < MAX_SCAN_POSITIONS) {
val start = (end - QUEUE_CHUNK + 1).coerceAtLeast(0)
collected.addAll(0, queueRepository.range(snapshot, start, end).filter(::visible))
scanned += end - start + 1
end = start - 1
}
if (collected.isEmpty()) return@withLock
@@ -201,9 +210,11 @@ class QueueViewModel(
if (last >= snapshot.size - 1) return@withLock
val collected = mutableListOf<QueueWindowItem>()
var start = last + 1
while (start < snapshot.size && collected.size < QUEUE_CHUNK) {
var scanned = 0L
while (start < snapshot.size && collected.size < QUEUE_CHUNK && scanned < MAX_SCAN_POSITIONS) {
val to = (start + QUEUE_CHUNK - 1).coerceAtMost(snapshot.size - 1)
collected.addAll(queueRepository.range(snapshot, start, to).filter(::visible))
scanned += to - start + 1
start = to + 1
}
if (collected.isEmpty()) return@withLock