From 796e5e28278e144844f33b81f1bed50e9a03c35d Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:10:47 +0000 Subject: [PATCH] queue the whole starred list from both starred song lists --- .../com/subtracks/data/db/LibraryDao.kt | 6 ++++++ .../subtracks/data/repo/LibraryRepository.kt | 2 ++ .../subtracks/ui/home/HomeListViewModel.kt | 6 +++++- .../com/subtracks/ui/home/HomeScreen.kt | 9 ++++----- .../com/subtracks/ui/home/HomeViewModel.kt | 19 +++++++++++++------ .../subtracks/data/db/LibraryHomeDaoTest.kt | 19 +++++++++++++++++++ 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt b/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt index edcee5b4..5923a284 100644 --- a/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt +++ b/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt @@ -704,6 +704,12 @@ interface LibraryDao { ) fun starredSongs(sourceId: Long): PagingSource + @Query( + "SELECT songs.id FROM songs WHERE sourceId = :sourceId AND starred IS NOT NULL " + + "ORDER BY starred DESC, title COLLATE NOCASE, id", + ) + suspend fun starredSongIds(sourceId: Long): List + @Query( "SELECT songs.*, albums.coverArt AS coverArt FROM songs " + "LEFT JOIN albums ON albums.sourceId = songs.sourceId AND albums.id = songs.albumId " + diff --git a/app/src/main/kotlin/com/subtracks/data/repo/LibraryRepository.kt b/app/src/main/kotlin/com/subtracks/data/repo/LibraryRepository.kt index b915e228..54daa20b 100644 --- a/app/src/main/kotlin/com/subtracks/data/repo/LibraryRepository.kt +++ b/app/src/main/kotlin/com/subtracks/data/repo/LibraryRepository.kt @@ -88,6 +88,8 @@ class LibraryRepository( fun starredSongs(sourceId: Long): Flow> = pager(60) { db.libraryDao().starredSongs(sourceId) } + suspend fun starredSongIds(sourceId: Long): List = db.libraryDao().starredSongIds(sourceId) + fun songsByGenre( sourceId: Long, genre: String, diff --git a/app/src/main/kotlin/com/subtracks/ui/home/HomeListViewModel.kt b/app/src/main/kotlin/com/subtracks/ui/home/HomeListViewModel.kt index 816d456f..7f8ab136 100644 --- a/app/src/main/kotlin/com/subtracks/ui/home/HomeListViewModel.kt +++ b/app/src/main/kotlin/com/subtracks/ui/home/HomeListViewModel.kt @@ -111,6 +111,10 @@ class HomeListViewModel( ): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail) fun play(song: Song) { - viewModelScope.playSongInContext(libraryRepository, playbackController, song) + if (request.section == HomeSection.RecentlyStarredSongs) { + viewModelScope.playStarredList(libraryRepository, playbackController, song) + } else { + viewModelScope.playSongInContext(libraryRepository, playbackController, song) + } } } diff --git a/app/src/main/kotlin/com/subtracks/ui/home/HomeScreen.kt b/app/src/main/kotlin/com/subtracks/ui/home/HomeScreen.kt index 0ebffdac..2daae559 100644 --- a/app/src/main/kotlin/com/subtracks/ui/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/home/HomeScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.AssistChip @@ -122,7 +121,7 @@ fun HomeScreen( bottomInset: Dp = 0.dp, onAlbumClick: (Album) -> Unit = {}, onArtistClick: (Artist) -> Unit = {}, - onPlayStarred: (List, Int) -> Unit = { _, _ -> }, + onPlayStarred: (Song) -> Unit = {}, onLongClick: (MenuTarget) -> Unit = {}, onMore: (HomeSection) -> Unit = {}, onGenreClick: (String) -> Unit = {}, @@ -361,7 +360,7 @@ private fun LazyListScope.starredSongs( songs: List, coverArt: (String?, Boolean) -> CoverArtRef?, playingSongId: String?, - onPlayStarred: (List, Int) -> Unit, + onPlayStarred: (Song) -> Unit, onLongClick: (MenuTarget) -> Unit, onMore: (HomeSection) -> Unit, ) { @@ -369,7 +368,7 @@ private fun LazyListScope.starredSongs( item(key = "${section.name}-header") { HomeSectionHeader(section.title) { onMore(section) } } - itemsIndexed(songs, key = { _, item -> item.song.id }) { index, item -> + items(songs, key = { it.song.id }) { item -> SongRow( song = item.song, coverArtId = item.coverArt, @@ -378,7 +377,7 @@ private fun LazyListScope.starredSongs( durationSeconds = item.song.duration, modifier = Modifier.combinedClickable( - onClick = { onPlayStarred(songs.map { it.song }, index) }, + onClick = { onPlayStarred(item.song) }, onLongClick = { onLongClick(MenuTarget.Song(item.song, coverArt(item.coverArt, true))) }, ), ) diff --git a/app/src/main/kotlin/com/subtracks/ui/home/HomeViewModel.kt b/app/src/main/kotlin/com/subtracks/ui/home/HomeViewModel.kt index 3cede552..5192506d 100644 --- a/app/src/main/kotlin/com/subtracks/ui/home/HomeViewModel.kt +++ b/app/src/main/kotlin/com/subtracks/ui/home/HomeViewModel.kt @@ -101,12 +101,8 @@ class HomeViewModel( thumbnail: Boolean, ): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail) - fun playStarred( - songs: List, - startIndex: Int, - ) { - val sourceId = songs.getOrNull(startIndex)?.sourceId ?: return - playbackController.playSongs(sourceId, songs.map { it.id }, startIndex) + fun playStarred(song: Song) { + viewModelScope.playStarredList(libraryRepository, playbackController, song) } fun sync() = syncManager.requestSync() @@ -166,3 +162,14 @@ internal fun CoroutineScope.playSongInContext( } } } + +internal fun CoroutineScope.playStarredList( + libraryRepository: LibraryRepository, + playbackController: PlaybackController, + song: Song, +) { + launch { + val ids = libraryRepository.starredSongIds(song.sourceId) + playbackController.playSongs(song.sourceId, ids, ids.indexOf(song.id).coerceAtLeast(0)) + } +} diff --git a/app/src/test/kotlin/com/subtracks/data/db/LibraryHomeDaoTest.kt b/app/src/test/kotlin/com/subtracks/data/db/LibraryHomeDaoTest.kt index 23d9c7cd..3475a826 100644 --- a/app/src/test/kotlin/com/subtracks/data/db/LibraryHomeDaoTest.kt +++ b/app/src/test/kotlin/com/subtracks/data/db/LibraryHomeDaoTest.kt @@ -316,6 +316,25 @@ class LibraryHomeDaoTest { assertEquals("cover-1", page.first().coverArt) } + @Test + fun starredSongIdsMatchTheDisplayedOrderSoTheStartTrackIsRight() = + runTest { + val sourceId = source() + val dao = db.libraryDao() + dao.upsertSongs( + listOf( + song(sourceId, "s1", "First", starred = 100), + song(sourceId, "s2", "Second", starred = 300), + song(sourceId, "s3", "Third", starred = null), + song(sourceId, "s4", "Fourth", starred = 200), + ), + ) + + val displayed = dao.starredSongs(sourceId).page().map { it.song.id } + assertEquals(listOf("s2", "s4", "s1"), displayed) + assertEquals(displayed, dao.starredSongIds(sourceId)) + } + @Test fun songsByGenrePagingFiltersAndJoinsAlbumCoverArt() = runTest {