mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
queue the whole starred list from both starred song lists
This commit is contained in:
@@ -704,6 +704,12 @@ interface LibraryDao {
|
|||||||
)
|
)
|
||||||
fun starredSongs(sourceId: Long): PagingSource<Int, AlbumSongItem>
|
fun starredSongs(sourceId: Long): PagingSource<Int, AlbumSongItem>
|
||||||
|
|
||||||
|
@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<String>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"SELECT songs.*, albums.coverArt AS coverArt FROM songs " +
|
"SELECT songs.*, albums.coverArt AS coverArt FROM songs " +
|
||||||
"LEFT JOIN albums ON albums.sourceId = songs.sourceId AND albums.id = songs.albumId " +
|
"LEFT JOIN albums ON albums.sourceId = songs.sourceId AND albums.id = songs.albumId " +
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ class LibraryRepository(
|
|||||||
|
|
||||||
fun starredSongs(sourceId: Long): Flow<PagingData<AlbumSongItem>> = pager(60) { db.libraryDao().starredSongs(sourceId) }
|
fun starredSongs(sourceId: Long): Flow<PagingData<AlbumSongItem>> = pager(60) { db.libraryDao().starredSongs(sourceId) }
|
||||||
|
|
||||||
|
suspend fun starredSongIds(sourceId: Long): List<String> = db.libraryDao().starredSongIds(sourceId)
|
||||||
|
|
||||||
fun songsByGenre(
|
fun songsByGenre(
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
genre: String,
|
genre: String,
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ class HomeListViewModel(
|
|||||||
): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail)
|
): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail)
|
||||||
|
|
||||||
fun play(song: Song) {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.AssistChip
|
import androidx.compose.material3.AssistChip
|
||||||
@@ -122,7 +121,7 @@ fun HomeScreen(
|
|||||||
bottomInset: Dp = 0.dp,
|
bottomInset: Dp = 0.dp,
|
||||||
onAlbumClick: (Album) -> Unit = {},
|
onAlbumClick: (Album) -> Unit = {},
|
||||||
onArtistClick: (Artist) -> Unit = {},
|
onArtistClick: (Artist) -> Unit = {},
|
||||||
onPlayStarred: (List<Song>, Int) -> Unit = { _, _ -> },
|
onPlayStarred: (Song) -> Unit = {},
|
||||||
onLongClick: (MenuTarget) -> Unit = {},
|
onLongClick: (MenuTarget) -> Unit = {},
|
||||||
onMore: (HomeSection) -> Unit = {},
|
onMore: (HomeSection) -> Unit = {},
|
||||||
onGenreClick: (String) -> Unit = {},
|
onGenreClick: (String) -> Unit = {},
|
||||||
@@ -361,7 +360,7 @@ private fun LazyListScope.starredSongs(
|
|||||||
songs: List<AlbumSongItem>,
|
songs: List<AlbumSongItem>,
|
||||||
coverArt: (String?, Boolean) -> CoverArtRef?,
|
coverArt: (String?, Boolean) -> CoverArtRef?,
|
||||||
playingSongId: String?,
|
playingSongId: String?,
|
||||||
onPlayStarred: (List<Song>, Int) -> Unit,
|
onPlayStarred: (Song) -> Unit,
|
||||||
onLongClick: (MenuTarget) -> Unit,
|
onLongClick: (MenuTarget) -> Unit,
|
||||||
onMore: (HomeSection) -> Unit,
|
onMore: (HomeSection) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -369,7 +368,7 @@ private fun LazyListScope.starredSongs(
|
|||||||
item(key = "${section.name}-header") {
|
item(key = "${section.name}-header") {
|
||||||
HomeSectionHeader(section.title) { onMore(section) }
|
HomeSectionHeader(section.title) { onMore(section) }
|
||||||
}
|
}
|
||||||
itemsIndexed(songs, key = { _, item -> item.song.id }) { index, item ->
|
items(songs, key = { it.song.id }) { item ->
|
||||||
SongRow(
|
SongRow(
|
||||||
song = item.song,
|
song = item.song,
|
||||||
coverArtId = item.coverArt,
|
coverArtId = item.coverArt,
|
||||||
@@ -378,7 +377,7 @@ private fun LazyListScope.starredSongs(
|
|||||||
durationSeconds = item.song.duration,
|
durationSeconds = item.song.duration,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.combinedClickable(
|
Modifier.combinedClickable(
|
||||||
onClick = { onPlayStarred(songs.map { it.song }, index) },
|
onClick = { onPlayStarred(item.song) },
|
||||||
onLongClick = { onLongClick(MenuTarget.Song(item.song, coverArt(item.coverArt, true))) },
|
onLongClick = { onLongClick(MenuTarget.Song(item.song, coverArt(item.coverArt, true))) },
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -101,12 +101,8 @@ class HomeViewModel(
|
|||||||
thumbnail: Boolean,
|
thumbnail: Boolean,
|
||||||
): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail)
|
): CoverArtRef? = sourceRepository.coverArt(coverArt, thumbnail)
|
||||||
|
|
||||||
fun playStarred(
|
fun playStarred(song: Song) {
|
||||||
songs: List<Song>,
|
viewModelScope.playStarredList(libraryRepository, playbackController, song)
|
||||||
startIndex: Int,
|
|
||||||
) {
|
|
||||||
val sourceId = songs.getOrNull(startIndex)?.sourceId ?: return
|
|
||||||
playbackController.playSongs(sourceId, songs.map { it.id }, startIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sync() = syncManager.requestSync()
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -316,6 +316,25 @@ class LibraryHomeDaoTest {
|
|||||||
assertEquals("cover-1", page.first().coverArt)
|
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
|
@Test
|
||||||
fun songsByGenrePagingFiltersAndJoinsAlbumCoverArt() =
|
fun songsByGenrePagingFiltersAndJoinsAlbumCoverArt() =
|
||||||
runTest {
|
runTest {
|
||||||
|
|||||||
Reference in New Issue
Block a user