koel/resources/assets/js/stores/artist.js

237 lines
5.1 KiB
JavaScript
Raw Normal View History

/*eslint camelcase: ["error", {properties: "never"}]*/
2016-11-26 03:25:35 +00:00
import Vue from 'vue'
2016-12-17 08:10:08 +00:00
import { reduce, each, union, difference, take, filter, orderBy } from 'lodash'
2015-12-13 04:42:28 +00:00
2016-11-26 03:25:35 +00:00
import config from '../config'
import stub from '../stubs/artist'
import { albumStore } from '.'
2015-12-13 04:42:28 +00:00
2016-11-26 03:25:35 +00:00
const UNKNOWN_ARTIST_ID = 1
const VARIOUS_ARTISTS_ID = 2
2016-04-17 15:38:06 +00:00
2016-06-25 10:15:57 +00:00
export const artistStore = {
2016-06-25 16:05:24 +00:00
stub,
2016-12-17 07:31:08 +00:00
cache: [],
2016-06-25 16:05:24 +00:00
state: {
2016-11-26 03:25:35 +00:00
artists: []
2016-06-25 16:05:24 +00:00
},
/**
* Init the store.
*
* @param {Array.<Object>} artists The array of artists we got from the server.
*/
2016-11-26 03:25:35 +00:00
init (artists) {
this.all = artists
2016-06-25 16:05:24 +00:00
// Traverse through artists array to get the cover and number of songs for each.
2017-01-12 16:50:00 +00:00
each(this.all, artist => this.setupArtist(artist))
albumStore.init(this.all)
2016-06-25 16:05:24 +00:00
},
/**
* Set up the (reactive) properties of an artist.
*
* @param {Object} artist
*/
2016-11-26 03:25:35 +00:00
setupArtist (artist) {
this.getImage(artist)
Vue.set(artist, 'playCount', 0)
2016-06-25 16:05:24 +00:00
// Here we build a list of songs performed by the artist, so that we don't need to traverse
// down the "artist > albums > items" route later.
// This also makes sure songs in compilation albums are counted as well.
Vue.set(artist, 'songs', reduce(artist.albums, (songs, album) => {
// If the album is compilation, we cater for the songs contributed by this artist only.
if (album.is_compilation) {
2016-11-26 03:25:35 +00:00
return songs.concat(filter(album.songs, { contributing_artist_id: artist.id }))
2016-06-25 16:05:24 +00:00
}
// Otherwise, just use all songs in the album.
2016-11-26 03:25:35 +00:00
return songs.concat(album.songs)
}, []))
2016-06-25 16:05:24 +00:00
2016-11-26 03:25:35 +00:00
Vue.set(artist, 'songCount', artist.songs.length)
Vue.set(artist, 'info', null)
this.cache[artist.id] = artist
2016-06-25 16:05:24 +00:00
2016-11-26 03:25:35 +00:00
return artist
2016-06-25 16:05:24 +00:00
},
/**
* Get all artists.
*
* @return {Array.<Object>}
*/
2016-11-26 03:25:35 +00:00
get all () {
return this.state.artists
2016-06-25 16:05:24 +00:00
},
/**
* Set all artists.
*
* @param {Array.<Object>} value
*/
2016-11-26 03:25:35 +00:00
set all (value) {
this.state.artists = value
2016-06-25 16:05:24 +00:00
},
/**
* Get an artist object by its ID.
*
* @param {Number} id
*/
2016-11-26 03:25:35 +00:00
byId (id) {
2016-12-17 07:31:08 +00:00
return this.cache[id]
2016-06-25 16:05:24 +00:00
},
/**
* Adds an artist/artists into the current collection.
*
* @param {Array.<Object>|Object} artists
*/
2016-11-26 03:25:35 +00:00
add (artists) {
artists = [].concat(artists)
2017-01-12 16:50:00 +00:00
each(artists, artist => this.setupArtist(artist))
2016-06-25 16:05:24 +00:00
2016-11-26 03:25:35 +00:00
this.all = union(this.all, artists)
2016-06-25 16:05:24 +00:00
},
/**
* Remove artist(s) from the store.
*
* @param {Array.<Object>|Object} artists
*/
2016-11-26 03:25:35 +00:00
remove (artists) {
2016-12-17 08:10:08 +00:00
artists = [].concat(artists)
this.all = difference(this.all, artists)
// Remember to clear the cache
2017-01-12 16:50:00 +00:00
each(artists, artist => delete this.cache[artist.id])
2016-06-25 16:05:24 +00:00
},
/**
* Add album(s) into an artist.
*
* @param {Object} artist
* @param {Array.<Object>|Object} albums
*
*/
2016-11-26 03:25:35 +00:00
addAlbumsIntoArtist (artist, albums) {
albums = [].concat(albums)
2016-06-25 16:05:24 +00:00
2017-01-17 14:09:27 +00:00
artist.albums = union(artist.albums || [], albums)
2016-06-25 16:05:24 +00:00
each(albums, album => {
2016-11-26 03:25:35 +00:00
album.artist_id = artist.id
album.artist = artist
artist.playCount += album.playCount
})
2016-06-25 16:05:24 +00:00
},
/**
* Remove album(s) from an artist.
*
* @param {Object} artist
* @param {Array.<Object>|Object} albums
*/
2016-11-26 03:25:35 +00:00
removeAlbumsFromArtist (artist, albums) {
albums = [].concat(albums)
artist.albums = difference(artist.albums, albums)
each(albums, album => {
artist.playCount -= album.playCount
})
2016-06-25 16:05:24 +00:00
},
/**
* Checks if an artist is empty.
*
* @param {Object} artist
*
* @return {boolean}
*/
2016-11-26 03:25:35 +00:00
isArtistEmpty (artist) {
return !artist.albums.length
2016-06-25 16:05:24 +00:00
},
/**
* Determine if the artist is the special "Various Artists".
*
* @param {Object} artist
*
* @return {Boolean}
*/
2016-11-26 03:25:35 +00:00
isVariousArtists (artist) {
return artist.id === VARIOUS_ARTISTS_ID
2016-06-25 16:05:24 +00:00
},
/**
* Determine if the artist is the special "Unknown Artist".
*
* @param {Object} artist [description]
*
* @return {Boolean}
*/
2016-11-26 03:25:35 +00:00
isUnknownArtist (artist) {
return artist.id === UNKNOWN_ARTIST_ID
2016-06-25 16:05:24 +00:00
},
/**
* Get all songs performed by an artist.
*
* @param {Object} artist
*
* @return {Array.<Object>}
*/
2016-11-26 03:25:35 +00:00
getSongsByArtist (artist) {
return artist.songs
2016-06-25 16:05:24 +00:00
},
/**
* Get the artist's image.
*
* @param {Object} artist
*
* @return {String}
*/
2016-11-26 03:25:35 +00:00
getImage (artist) {
2016-06-25 16:05:24 +00:00
if (!artist.image) {
// Try to get an image from one of the albums.
2016-11-26 03:25:35 +00:00
artist.image = config.unknownCover
2016-06-25 16:05:24 +00:00
artist.albums.every(album => {
// If there's a "real" cover, use it.
if (album.image !== config.unknownCover) {
2016-11-26 03:25:35 +00:00
artist.image = album.cover
2016-06-25 16:05:24 +00:00
// I want to break free.
2016-11-26 03:25:35 +00:00
return false
2015-12-22 09:53:03 +00:00
}
2016-11-26 03:25:35 +00:00
})
2016-06-25 16:05:24 +00:00
}
2016-11-26 03:25:35 +00:00
return artist.image
2016-06-25 16:05:24 +00:00
},
/**
* Get top n most-played artists.
*
* @param {Number} n
*
* @return {Array.<Object>}
*/
2016-11-26 03:25:35 +00:00
getMostPlayed (n = 6) {
2016-06-25 16:05:24 +00:00
// Only non-unknown artists with actually play count are applicable.
// Also, "Various Artists" doesn't count.
const applicable = filter(this.all, artist => {
2016-11-26 03:25:35 +00:00
return artist.playCount &&
!this.isUnknownArtist(artist) &&
!this.isVariousArtists(artist)
})
return take(orderBy(applicable, 'playCount', 'desc'), n)
}
}