download a song's playlist artwork too

This commit is contained in:
austinried
2026-10-04 00:30:04 +00:00
parent 410b13c920
commit 3e042cb380
4 changed files with 61 additions and 7 deletions
@@ -8,6 +8,7 @@ import com.subtracks.data.model.DownloadedSong
import com.subtracks.data.model.EntityDownloadStatus
import com.subtracks.data.model.ListDownloadStatus
import com.subtracks.data.model.SongDownload
import com.subtracks.data.model.SourceCoverArt
import kotlinx.coroutines.flow.Flow
@Dao
@@ -125,6 +126,25 @@ interface DownloadDao {
)
suspend fun artwork(): List<DownloadArtwork>
@Query(
"SELECT DISTINCT p.coverArt AS coverArt FROM playlist_songs ps " +
"JOIN playlists p ON p.sourceId = ps.sourceId AND p.id = ps.playlistId " +
"WHERE ps.sourceId = :sourceId AND ps.songId = :songId AND p.coverArt IS NOT NULL",
)
suspend fun playlistCoversForSong(
sourceId: Long,
songId: String,
): List<String>
@Query(
"SELECT DISTINCT ps.sourceId AS sourceId, p.coverArt AS coverArt " +
"FROM playlist_songs ps " +
"JOIN playlists p ON p.sourceId = ps.sourceId AND p.id = ps.playlistId " +
"JOIN song_downloads d ON d.sourceId = ps.sourceId AND d.songId = ps.songId " +
"WHERE p.coverArt IS NOT NULL",
)
suspend fun downloadedPlaylistCovers(): List<SourceCoverArt>
@Query("SELECT * FROM song_downloads WHERE sourceId = :sourceId AND songId = :songId")
suspend fun find(
sourceId: Long,
@@ -86,6 +86,11 @@ data class DownloadArtwork(
get() = (albumId != null && albumRow == null) || (artistId != null && artistRow == null)
}
data class SourceCoverArt(
val sourceId: Long,
val coverArt: String,
)
class DownloadStatusConverter {
@ColumnTypeConverter
fun fromDownloadStatus(status: DownloadStatus): String = status.name
@@ -388,9 +388,11 @@ class DownloadRepository(
) {
val song = db.libraryDao().songOnce(sourceId, songId)
val coverArt =
listOfNotNull(
song?.albumId?.let { db.libraryDao().albumOnce(sourceId, it)?.coverArt },
song?.artistId?.let { db.libraryDao().artistOnce(sourceId, it)?.coverArt },
(
listOfNotNull(
song?.albumId?.let { db.libraryDao().albumOnce(sourceId, it)?.coverArt },
song?.artistId?.let { db.libraryDao().artistOnce(sourceId, it)?.coverArt },
) + db.downloadDao().playlistCoversForSong(sourceId, songId)
).distinct()
coverArt.forEach { cover ->
storeArtwork(sourceId, cover, thumbnail = false)
@@ -423,18 +425,22 @@ class DownloadRepository(
* rows could not all be resolved against the library, in which case nothing is swept for it:
* pruning an album or artist would otherwise delete artwork a download still holds.
*/
private suspend fun artworkToKeep(): Map<Long, Set<String>?> =
db
private suspend fun artworkToKeep(): Map<Long, Set<String>?> {
val playlistCovers = db.downloadDao().downloadedPlaylistCovers().groupBy({ it.sourceId }, { it.coverArt })
return db
.downloadDao()
.artwork()
.groupBy { it.sourceId }
.mapValues { (sourceId, rows) ->
if (rows.any { it.hasMissingLibraryRow }) return@mapValues null
rows
.flatMap { row -> listOfNotNull(row.albumCoverArt, row.artistCoverArt) }
val covers =
rows.flatMap { row -> listOfNotNull(row.albumCoverArt, row.artistCoverArt) } +
playlistCovers[sourceId].orEmpty()
covers
.flatMap { cover -> listOf(false, true).map { thumbnail -> coverArtKey(sourceId, cover, thumbnail) } }
.toSet()
}
}
private suspend fun recover(row: SongDownload) {
when (row.status) {