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

92 lines
2.5 KiB
TypeScript
Raw Normal View History

2022-06-10 10:47:46 +00:00
import { reactive } from 'vue'
2022-04-21 09:38:24 +00:00
import { difference, orderBy, take, union } from 'lodash'
2022-04-24 08:50:45 +00:00
import { httpService } from '@/services'
2022-06-10 10:47:46 +00:00
import { arrayify } from '@/utils'
import { songStore } from '@/stores'
2022-07-04 10:38:06 +00:00
import { Cache } from '@/services/cache'
2022-04-15 14:24:30 +00:00
const UNKNOWN_ALBUM_ID = 1
export const albumStore = {
2022-06-10 10:47:46 +00:00
vault: new Map<number, Album>(),
2022-04-15 14:24:30 +00:00
2022-06-10 10:47:46 +00:00
state: reactive({
2022-04-21 09:38:24 +00:00
albums: []
}),
2022-04-15 14:24:30 +00:00
2022-06-10 10:47:46 +00:00
byId (id: number) {
return this.vault.get(id)
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
removeByIds (ids: number[]) {
this.state.albums = difference(this.state.albums, ids.map(id => this.byId(id)))
ids.forEach(id => this.vault.delete(id))
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
/**
* Upload a cover for an album.
*
* @param {Album} album The album object
* @param {string} cover The content data string of the cover
*/
uploadCover: async (album: Album, cover: string) => {
album.cover = (await httpService.put<{ coverUrl: string }>(`album/${album.id}/cover`, { cover })).coverUrl
songStore.byAlbum(album).forEach(song => song.album_cover = album.cover)
return album.cover
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
/**
* Fetch the (blurry) thumbnail-sized version of an album's cover.
*/
fetchThumbnail: async (id: number) => {
return (await httpService.get<{ thumbnailUrl: string }>(`album/${id}/thumbnail`)).thumbnailUrl
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
isUnknown: (album: Album | number) => {
if (typeof album === 'number') return album === UNKNOWN_ALBUM_ID
return album.id === UNKNOWN_ALBUM_ID
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
syncWithVault (albums: Album | Album[]) {
return arrayify(albums).map(album => {
let local = this.vault.get(album.id)
local = reactive(local ? Object.assign(local, album) : album)
this.vault.set(album.id, local)
2022-04-15 14:24:30 +00:00
2022-06-10 10:47:46 +00:00
return local
})
2022-04-28 09:00:20 +00:00
},
2022-06-10 10:47:46 +00:00
async resolve (id: number) {
let album = this.byId(id)
2022-04-15 14:24:30 +00:00
2022-06-10 10:47:46 +00:00
if (!album) {
album = await Cache.resolve<Album>(['album', id], async () => await httpService.get<Album>(`albums/${id}`))
2022-06-10 10:47:46 +00:00
this.syncWithVault(album)
2022-04-15 14:24:30 +00:00
}
2022-06-10 10:47:46 +00:00
return album
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
async fetch (page: number) {
const resource = await httpService.get<PaginatorResource>(`albums?page=${page}`)
this.state.albums = union(this.state.albums, this.syncWithVault(resource.data))
2022-04-15 14:24:30 +00:00
2022-06-10 10:47:46 +00:00
return resource.links.next ? ++resource.meta.current_page : null
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
getMostPlayed (count: number) {
return take(
orderBy(Array.from(this.vault.values()).filter(album => !this.isUnknown(album)), 'play_count', 'desc'),
count
)
2022-04-15 14:24:30 +00:00
},
2022-06-10 10:47:46 +00:00
getRecentlyAdded (count: number) {
return take(
orderBy(Array.from(this.vault.values()).filter(album => !this.isUnknown(album)), 'created_at', 'desc'),
count
)
}
2022-04-15 14:24:30 +00:00
}