added back fix for song cover art

This commit is contained in:
austinried
2022-03-21 16:12:06 +09:00
parent ba37348fc3
commit d59dcc2481

View File

@@ -22,12 +22,15 @@ import {
Search3Response, Search3Response,
SubsonicResponse, SubsonicResponse,
} from '@app/subsonic/responses' } from '@app/subsonic/responses'
import PromiseQueue from '@app/util/PromiseQueue'
import { reduceById, mergeById } from '@app/util/state' import { reduceById, mergeById } from '@app/util/state'
import produce from 'immer' import produce from 'immer'
import { WritableDraft } from 'immer/dist/types/types-external' import { WritableDraft } from 'immer/dist/types/types-external'
import pick from 'lodash.pick' import pick from 'lodash.pick'
import { GetState, SetState } from 'zustand' import { GetState, SetState } from 'zustand'
const songCoverArtQueue = new PromiseQueue(2)
export type LibrarySlice = { export type LibrarySlice = {
entities: { entities: {
artists: ById<Artist> artists: ById<Artist>
@@ -62,6 +65,8 @@ export type LibrarySlice = {
fetchLibrarySearchResults: (params: Search3Params) => Promise<SearchResults> fetchLibrarySearchResults: (params: Search3Params) => Promise<SearchResults>
star: (params: StarParams) => Promise<void> star: (params: StarParams) => Promise<void>
unstar: (params: StarParams) => Promise<void> unstar: (params: StarParams) => Promise<void>
_fixSongCoverArt: (songs: Song[]) => Promise<void>
} }
const defaultEntities = () => ({ const defaultEntities = () => ({
@@ -180,6 +185,8 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
const topSongs = response.data.songs.map(mapSong) const topSongs = response.data.songs.map(mapSong)
const topSongsById = reduceById(topSongs) const topSongsById = reduceById(topSongs)
get()._fixSongCoverArt(topSongs)
set( set(
produce<LibrarySlice>(state => { produce<LibrarySlice>(state => {
mergeById(state.entities.songs, topSongsById) mergeById(state.entities.songs, topSongsById)
@@ -205,6 +212,8 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
const songs = response.data.songs.map(mapSong) const songs = response.data.songs.map(mapSong)
const songsById = reduceById(songs) const songsById = reduceById(songs)
get()._fixSongCoverArt(songs)
set( set(
produce<LibrarySlice>(state => { produce<LibrarySlice>(state => {
state.entities.albums[id] = album state.entities.albums[id] = album
@@ -255,6 +264,8 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
const songs = response.data.playlist.songs.map(mapSong) const songs = response.data.playlist.songs.map(mapSong)
const songsById = reduceById(songs) const songsById = reduceById(songs)
get()._fixSongCoverArt(songs)
set( set(
produce<LibrarySlice>(state => { produce<LibrarySlice>(state => {
state.entities.playlists[id] = playlist state.entities.playlists[id] = playlist
@@ -279,6 +290,8 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
const song = mapSong(response.data.song) const song = mapSong(response.data.song)
get()._fixSongCoverArt([song])
set( set(
produce<LibrarySlice>(state => { produce<LibrarySlice>(state => {
state.entities.songs[id] = song state.entities.songs[id] = song
@@ -333,6 +346,8 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
const songs = response.data.songs.map(mapSong) const songs = response.data.songs.map(mapSong)
const songsById = reduceById(songs) const songsById = reduceById(songs)
get()._fixSongCoverArt(songs)
set( set(
produce<LibrarySlice>(state => { produce<LibrarySlice>(state => {
mergeById(state.entities.artists, artistsById) mergeById(state.entities.artists, artistsById)
@@ -433,6 +448,48 @@ export const createLibrarySlice = (set: SetState<Store>, get: GetState<Store>):
) )
} }
}, },
// song cover art comes back from the api as a unique id per song even if it all points to the same
// album art, which prevents us from caching it once, so we need to use the album's cover art
_fixSongCoverArt: async songs => {
const client = get().client
if (!client) {
return
}
const albumsToGet: ById<Song[]> = {}
for (const song of songs) {
if (!song.albumId) {
continue
}
let album = get().entities.albums[song.albumId]
if (album) {
song.coverArt = album.coverArt
continue
}
albumsToGet[song.albumId] = albumsToGet[song.albumId] || []
albumsToGet[song.albumId].push(song)
}
for (const id in albumsToGet) {
songCoverArtQueue
.enqueue(() => client.getAlbum({ id }))
.then(res => {
const album = mapAlbum(res.data.album)
set(
produce<LibrarySlice>(state => {
state.entities.albums[album.id] = album
for (const song of albumsToGet[album.id]) {
state.entities.songs[song.id].coverArt = album.coverArt
}
}),
)
})
}
},
}) })
function mapArtist(artist: ArtistID3Element): Artist { function mapArtist(artist: ArtistID3Element): Artist {
@@ -488,7 +545,6 @@ function mapSong(song: ChildElement): Song {
discNumber: song.discNumber, discNumber: song.discNumber,
duration: song.duration, duration: song.duration,
starred: song.starred, starred: song.starred,
coverArt: song.coverArt,
} }
} }