koel/resources/assets/js/stores/album.ts

113 lines
2.9 KiB
TypeScript
Raw Normal View History

2022-04-21 09:38:24 +00:00
import { difference, orderBy, take, union } from 'lodash'
2022-04-15 14:24:30 +00:00
import { artistStore } from '.'
import { http } from '@/services'
2022-04-20 09:37:22 +00:00
import { arrayify, use } from '@/utils'
2022-04-21 09:38:24 +00:00
import { reactive } from 'vue'
interface AlbumStoreState {
albums: Album[]
}
2022-04-15 14:24:30 +00:00
const UNKNOWN_ALBUM_ID = 1
export const albumStore = {
2022-04-21 09:38:24 +00:00
cache: {} as Record<number, Album>,
2022-04-15 14:24:30 +00:00
2022-04-21 09:38:24 +00:00
state: reactive<AlbumStoreState>({
albums: []
}),
2022-04-15 14:24:30 +00:00
init (albums: Album[]) {
// Traverse through the artists array and add their albums into our master album list.
this.all = albums
this.all.forEach(album => this.setupAlbum(album))
},
2022-04-21 09:38:24 +00:00
setupAlbum (album: Album) {
2022-04-15 14:24:30 +00:00
const artist = artistStore.byId(album.artist_id)!
artist.albums = union(artist.albums, [album])
album.artist = artist
album.info = null
album.songs = []
album.playCount = 0
this.cache[album.id] = album
},
get all () {
return this.state.albums
},
set all (value) {
this.state.albums = value
},
2022-04-21 09:38:24 +00:00
byId (id: number) {
2022-04-15 14:24:30 +00:00
return this.cache[id]
},
2022-04-21 09:38:24 +00:00
byIds (ids: number[]) {
2022-04-15 14:24:30 +00:00
const albums = [] as Album[]
ids.forEach(id => use(this.byId(id), album => albums.push(album!)))
return albums
},
2022-04-21 09:38:24 +00:00
add (albums: Album | Album[]) {
2022-04-20 09:37:22 +00:00
arrayify(albums).forEach(album => {
2022-04-15 14:24:30 +00:00
this.setupAlbum(album)
album.playCount = album.songs.reduce((count, song) => count + song.playCount, 0)
this.all.push(album)
})
},
/**
* Remove empty albums from the store.
*/
2022-04-21 09:38:24 +00:00
compact () {
2022-04-15 14:24:30 +00:00
const emptyAlbums = this.all.filter(album => album.songs.length === 0)
if (!emptyAlbums.length) {
return
}
this.all = difference(this.all, emptyAlbums)
emptyAlbums.forEach(album => delete this.cache[album.id])
},
2022-04-21 09:38:24 +00:00
getMostPlayed (count = 6): Album[] {
2022-04-15 14:24:30 +00:00
// Only non-unknown albums with actual play count are applicable.
2022-04-23 22:47:21 +00:00
const applicable = this.all.filter(album => album.playCount && !this.isUnknownAlbum(album))
2022-04-21 09:38:24 +00:00
return take(orderBy(applicable, 'playCount', 'desc'), count)
2022-04-15 14:24:30 +00:00
},
2022-04-21 09:38:24 +00:00
getRecentlyAdded (count = 6): Album[] {
2022-04-23 22:47:21 +00:00
const applicable = this.all.filter(album => !this.isUnknownAlbum(album))
2022-04-21 09:38:24 +00:00
return take(orderBy(applicable, 'created_at', 'desc'), count)
2022-04-15 14:24:30 +00:00
},
/**
* Upload a cover for an album.
*
* @param {Album} album The album object
* @param {string} cover The content data string of the cover
*/
2022-04-21 09:38:24 +00:00
uploadCover: async (album: Album, cover: string) => {
2022-04-23 22:47:21 +00:00
album.cover = (await http.put<{ coverUrl: string }>(`album/${album.id}/cover`, { cover })).coverUrl
2022-04-15 14:24:30 +00:00
return album.cover
},
/**
* Get the (blurry) thumbnail-sized version of an album's cover.
*/
2022-04-21 09:38:24 +00:00
getThumbnail: async (album: Album) => {
2022-04-15 14:24:30 +00:00
if (album.thumbnail === undefined) {
2022-04-23 22:47:21 +00:00
album.thumbnail = (await http.get<{ thumbnailUrl: string }>(`album/${album.id}/thumbnail`)).thumbnailUrl
2022-04-15 14:24:30 +00:00
}
return album.thumbnail
},
isUnknownAlbum: (album: Album) => album.id === UNKNOWN_ALBUM_ID
}