import Vue from 'vue' import { reduce, each, find, union, difference, take, filter, orderBy } from 'lodash' import config from '../config' import stub from '../stubs/artist' import { albumStore } from '.' const UNKNOWN_ARTIST_ID = 1 const VARIOUS_ARTISTS_ID = 2 export const artistStore = { stub, state: { artists: [] }, /** * Init the store. * * @param {Array.} artists The array of artists we got from the server. */ init (artists) { this.all = artists albumStore.init(this.all) // Traverse through artists array to get the cover and number of songs for each. each(this.all, artist => { this.setupArtist(artist) }) }, /** * Set up the (reactive) properties of an artist. * * @param {Object} artist */ setupArtist (artist) { this.getImage(artist) Vue.set(artist, 'playCount', 0) // 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) { return songs.concat(filter(album.songs, { contributing_artist_id: artist.id })) } // Otherwise, just use all songs in the album. return songs.concat(album.songs) }, [])) Vue.set(artist, 'songCount', artist.songs.length) Vue.set(artist, 'info', null) return artist }, /** * Get all artists. * * @return {Array.} */ get all () { return this.state.artists }, /** * Set all artists. * * @param {Array.} value */ set all (value) { this.state.artists = value }, /** * Get an artist object by its ID. * * @param {Number} id */ byId (id) { return find(this.all, { id }) }, /** * Adds an artist/artists into the current collection. * * @param {Array.|Object} artists */ add (artists) { artists = [].concat(artists) each(artists, a => this.setupArtist(a)) this.all = union(this.all, artists) }, /** * Remove artist(s) from the store. * * @param {Array.|Object} artists */ remove (artists) { this.all = difference(this.all, [].concat(artists)) }, /** * Add album(s) into an artist. * * @param {Object} artist * @param {Array.|Object} albums * */ addAlbumsIntoArtist (artist, albums) { albums = [].concat(albums) artist.albums = union(artist.albums ? artist.albums : [], albums) each(albums, album => { album.artist_id = artist.id album.artist = artist artist.playCount += album.playCount }) }, /** * Remove album(s) from an artist. * * @param {Object} artist * @param {Array.|Object} albums */ removeAlbumsFromArtist (artist, albums) { albums = [].concat(albums) artist.albums = difference(artist.albums, albums) each(albums, album => { artist.playCount -= album.playCount }) }, /** * Checks if an artist is empty. * * @param {Object} artist * * @return {boolean} */ isArtistEmpty (artist) { return !artist.albums.length }, /** * Determine if the artist is the special "Various Artists". * * @param {Object} artist * * @return {Boolean} */ isVariousArtists (artist) { return artist.id === VARIOUS_ARTISTS_ID }, /** * Determine if the artist is the special "Unknown Artist". * * @param {Object} artist [description] * * @return {Boolean} */ isUnknownArtist (artist) { return artist.id === UNKNOWN_ARTIST_ID }, /** * Get all songs performed by an artist. * * @param {Object} artist * * @return {Array.} */ getSongsByArtist (artist) { return artist.songs }, /** * Get the artist's image. * * @param {Object} artist * * @return {String} */ getImage (artist) { if (!artist.image) { // Try to get an image from one of the albums. artist.image = config.unknownCover artist.albums.every(album => { // If there's a "real" cover, use it. if (album.image !== config.unknownCover) { artist.image = album.cover // I want to break free. return false } }) } return artist.image }, /** * Get top n most-played artists. * * @param {Number} n * * @return {Array.} */ getMostPlayed (n = 6) { // Only non-unknown artists with actually play count are applicable. // Also, "Various Artists" doesn't count. const applicable = filter(this.all, artist => { return artist.playCount && !this.isUnknownArtist(artist) && !this.isVariousArtists(artist) }) return take(orderBy(applicable, 'playCount', 'desc'), n) } }