home: play the whole genre list from a genre song row

This commit is contained in:
austinried
2026-10-04 00:30:06 +00:00
parent f62e8363de
commit d9aa18c37a
5 changed files with 50 additions and 4 deletions
@@ -726,6 +726,21 @@ interface LibraryDao {
genre: String, genre: String,
): PagingSource<Int, AlbumSongItem> ): PagingSource<Int, AlbumSongItem>
@Query(
"SELECT songs.id FROM songs " +
"WHERE songs.sourceId = :sourceId AND (" +
"EXISTS (SELECT 1 FROM song_genres " +
"WHERE song_genres.sourceId = songs.sourceId AND song_genres.songId = songs.id " +
"AND song_genres.genre = :genre) " +
"OR (songs.genre = :genre AND NOT EXISTS (SELECT 1 FROM song_genres " +
"WHERE song_genres.sourceId = songs.sourceId AND song_genres.songId = songs.id))) " +
"ORDER BY songs.title COLLATE NOCASE, songs.id",
)
suspend fun songsByGenreIds(
sourceId: Long,
genre: String,
): List<String>
@Query( @Query(
"SELECT * FROM albums WHERE sourceId = :sourceId AND year >= :start AND year < :end " + "SELECT * FROM albums WHERE sourceId = :sourceId AND year >= :start AND year < :end " +
"ORDER BY year DESC, name COLLATE NOCASE, id", "ORDER BY year DESC, name COLLATE NOCASE, id",
@@ -95,6 +95,11 @@ class LibraryRepository(
genre: String, genre: String,
): Flow<PagingData<AlbumSongItem>> = pager(60) { db.libraryDao().songsByGenre(sourceId, genre) } ): Flow<PagingData<AlbumSongItem>> = pager(60) { db.libraryDao().songsByGenre(sourceId, genre) }
suspend fun genreSongIds(
sourceId: Long,
genre: String,
): List<String> = db.libraryDao().songsByGenreIds(sourceId, genre)
fun albumsByDecade( fun albumsByDecade(
sourceId: Long, sourceId: Long,
decade: Long, decade: Long,
@@ -111,10 +111,23 @@ class HomeListViewModel(
): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail) ): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail)
fun play(song: Song) { fun play(song: Song) {
if (request.section == HomeSection.RecentlyStarredSongs) { val genre = request.genre
viewModelScope.playStarredList(libraryRepository, playbackController, song) when {
} else { genre != null -> {
viewModelScope.playSongInContext(libraryRepository, playbackController, song) viewModelScope.playGenreList(libraryRepository, playbackController, genre, song)
}
request.section == HomeSection.RecentlyStarredSongs -> {
viewModelScope.playStarredList(
libraryRepository,
playbackController,
song,
)
}
else -> {
viewModelScope.playSongInContext(libraryRepository, playbackController, song)
}
} }
} }
} }
@@ -173,3 +173,15 @@ internal fun CoroutineScope.playStarredList(
playbackController.playSongs(song.sourceId, ids, ids.indexOf(song.id).coerceAtLeast(0)) playbackController.playSongs(song.sourceId, ids, ids.indexOf(song.id).coerceAtLeast(0))
} }
} }
internal fun CoroutineScope.playGenreList(
libraryRepository: LibraryRepository,
playbackController: PlaybackController,
genre: String,
song: Song,
) {
launch {
val ids = libraryRepository.genreSongIds(song.sourceId, genre)
playbackController.playSongs(song.sourceId, ids, ids.indexOf(song.id).coerceAtLeast(0))
}
}
@@ -182,6 +182,7 @@ class LibraryHomeDaoTest {
val page = dao.songsByGenre(sourceId, "Rock").page() val page = dao.songsByGenre(sourceId, "Rock").page()
assertEquals(listOf("s1", "s2"), page.map { it.song.id }) assertEquals(listOf("s1", "s2"), page.map { it.song.id })
assertEquals("cover-1", page.first().coverArt) assertEquals("cover-1", page.first().coverArt)
assertEquals(page.map { it.song.id }, dao.songsByGenreIds(sourceId, "Rock"))
} }
private suspend fun insertGenre( private suspend fun insertGenre(