Playlists stored in universal store, indexes stored for each view
This commit is contained in:
5
src/js/bootstrap.js
vendored
5
src/js/bootstrap.js
vendored
@ -65,6 +65,11 @@ var initialState = {
|
||||
playlists: [],
|
||||
tracks: []
|
||||
},
|
||||
library_artists: [],
|
||||
artists: [],
|
||||
library_albums: [],
|
||||
albums: [],
|
||||
library_playlists: [],
|
||||
playlists: [],
|
||||
notifications: []
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export default class GridItem extends React.Component{
|
||||
<div className="name">{ item.name }</div>
|
||||
<div className="secondary">
|
||||
{ item.artists ? <ArtistSentence artists={ item.artists } /> : null }
|
||||
{ item.type == 'playlist' && item.tracks ? item.tracks.total+' tracks' : null }
|
||||
{ item.type == 'playlist' && item.tracks_total ? item.tracks_total+' tracks' : null }
|
||||
{ item.followers ? item.followers.total.toLocaleString()+' followers' : null }
|
||||
{ item.type == 'playlist' && item.can_edit ? <FontAwesome name="edit" /> : null }
|
||||
</div>
|
||||
|
||||
@ -245,7 +245,7 @@ class TrackList extends React.Component{
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.state.tracks ) return null
|
||||
if( !this.state.tracks || Object.prototype.toString.call(this.state.tracks) !== '[object Array]' ) return null
|
||||
|
||||
let self = this;
|
||||
return (
|
||||
|
||||
@ -93,6 +93,28 @@ export let getTrackIcon = function( track = false ){
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a track's icon
|
||||
* @param track object
|
||||
* @return string
|
||||
**/
|
||||
export let flattenTracks = function( tracks ){
|
||||
var flattened = []
|
||||
for( var i = 0; i < tracks.length; i++ ){
|
||||
flattened.push( Object.assign(
|
||||
{},
|
||||
tracks[i].track,
|
||||
{
|
||||
added_by: tracks[i].added_by,
|
||||
added_at: tracks[i].added_at
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -12,7 +12,7 @@ const localstorageMiddleware = (function(){
|
||||
|
||||
// append our state to a global variable. This gives us access to debug the store at any point
|
||||
window._store = store
|
||||
//console.log(action)
|
||||
console.log(action)
|
||||
|
||||
switch( action.type ){
|
||||
|
||||
|
||||
@ -157,47 +157,47 @@ export function deletePlaylist( uri ){
|
||||
}
|
||||
}
|
||||
|
||||
export function getPlaylists(){
|
||||
return { type: 'MOPIDY_PLAYLISTS' }
|
||||
export function getLibraryPlaylists(){
|
||||
return { type: 'MOPIDY_GET_LIBRARY_PLAYLISTS' }
|
||||
}
|
||||
|
||||
export function getPlaylist( uri ){
|
||||
return {
|
||||
type: 'MOPIDY_PLAYLIST',
|
||||
type: 'MOPIDY_GET_PLAYLIST',
|
||||
data: { uri: uri }
|
||||
}
|
||||
}
|
||||
|
||||
export function getDirectory( uri ){
|
||||
return {
|
||||
type: 'MOPIDY_DIRECTORY',
|
||||
type: 'MOPIDY_GET_DIRECTORY',
|
||||
data: { uri: uri }
|
||||
}
|
||||
}
|
||||
|
||||
export function getAlbum( uri ){
|
||||
return {
|
||||
type: 'MOPIDY_ALBUM',
|
||||
type: 'MOPIDY_GET_ALBUM',
|
||||
data: { uri: uri }
|
||||
}
|
||||
}
|
||||
|
||||
export function getArtist( uri ){
|
||||
return {
|
||||
type: 'MOPIDY_ARTIST',
|
||||
type: 'MOPIDY_GET_ARTIST',
|
||||
data: { uri: uri }
|
||||
}
|
||||
}
|
||||
|
||||
export function getArtists(){
|
||||
return {
|
||||
type: 'MOPIDY_ARTISTS'
|
||||
type: 'MOPIDY_GET_ARTISTS'
|
||||
}
|
||||
}
|
||||
|
||||
export function getAlbums(){
|
||||
return {
|
||||
type: 'MOPIDY_ALBUMS'
|
||||
type: 'MOPIDY_GET_ALBUMS'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -282,29 +282,47 @@ const MopidyMiddleware = (function(){
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_PLAYLISTS':
|
||||
|
||||
/**
|
||||
* =============================================================== PLAYLIST(S) ==========
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
case 'MOPIDY_GET_LIBRARY_PLAYLISTS':
|
||||
instruct( socket, store, 'playlists.asList' )
|
||||
.then( response => {
|
||||
for( var i = 0; i < response.length; i++ ){
|
||||
if( response[i].uri.startsWith('m3u:')) response[i] = Object.assign({}, response[i], { can_edit: true })
|
||||
}
|
||||
store.dispatch({ type: 'MOPIDY_PLAYLISTS_LOADED', data: response });
|
||||
|
||||
// TODO: dispatch an action to fetch extra data for each playlist
|
||||
// this will then trigger an PLAYLIST_REFRESHED action to update a specific store item
|
||||
// drop in our URI list
|
||||
var playlist_uris = helpers.asURIs(response)
|
||||
|
||||
store.dispatch({ type: 'LIBRARY_PLAYLISTS_LOADED', uris: playlist_uris });
|
||||
|
||||
// get the full playlist objects
|
||||
for (var i = 0; i < response.length; i++ ){
|
||||
instruct( socket, store, 'playlists.lookup', { uri: response[i].uri })
|
||||
.then( response => {
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
{
|
||||
images: []
|
||||
},
|
||||
{
|
||||
can_edit: (response.uri.startsWith('m3u:'))
|
||||
},
|
||||
response,
|
||||
{
|
||||
tracks: ( response.tracks ? response.tracks : [] ),
|
||||
tracks_total: ( response.tracks ? response.tracks.length : 0 )
|
||||
}
|
||||
)
|
||||
|
||||
store.dispatch({ type: 'PLAYLIST_LOADED', playlist: playlist })
|
||||
})
|
||||
}
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_CREATE_PLAYLIST':
|
||||
instruct( socket, store, 'playlists.create', { name: action.name, uri_scheme: action.scheme })
|
||||
.then( response => {
|
||||
|
||||
// re-load our global playlists
|
||||
store.dispatch({ type: 'MOPIDY_PLAYLISTS' });
|
||||
});
|
||||
break
|
||||
|
||||
case 'MOPIDY_PLAYLIST':
|
||||
case 'MOPIDY_GET_PLAYLIST':
|
||||
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: false });
|
||||
instruct( socket, store, 'playlists.lookup', action.data )
|
||||
.then( response => {
|
||||
@ -321,18 +339,15 @@ const MopidyMiddleware = (function(){
|
||||
)
|
||||
|
||||
// tracks? get the full track objects
|
||||
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_PLAYLIST_TRACKS', tracks: playlist.tracks })
|
||||
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_RESOLVE_PLAYLIST_TRACKS', tracks: playlist.tracks })
|
||||
|
||||
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: playlist })
|
||||
store.dispatch({ type: 'PLAYLIST_LOADED', playlist: playlist })
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_PLAYLIST_TRACKS':
|
||||
case 'MOPIDY_RESOLVE_PLAYLIST_TRACKS':
|
||||
var tracks = Object.assign([], action.tracks)
|
||||
var uris = [];
|
||||
for( var i = 0; i < tracks.length; i++ ){
|
||||
uris.push( tracks[i].uri );
|
||||
}
|
||||
var uris = helpers.asURIs(tracks)
|
||||
|
||||
instruct( socket, store, 'library.lookup', { uris: uris } )
|
||||
.then( response => {
|
||||
@ -357,7 +372,7 @@ const MopidyMiddleware = (function(){
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatch({ type: 'PLAYLIST_TRACKS_LOADED', tracks: tracks })
|
||||
store.dispatch({ type: 'PLAYLIST_TRACKS_LOADED', playlist_uri: action.playlist_uri, tracks: tracks })
|
||||
})
|
||||
break
|
||||
|
||||
@ -460,14 +475,37 @@ const MopidyMiddleware = (function(){
|
||||
});
|
||||
break
|
||||
|
||||
case 'MOPIDY_CREATE_PLAYLIST':
|
||||
instruct( socket, store, 'playlists.create', { name: action.name, uri_scheme: action.scheme })
|
||||
.then( response => {
|
||||
|
||||
// re-load our global playlists
|
||||
//store.dispatch({ type: 'MOPIDY_GET_PLAYLISTS' });
|
||||
});
|
||||
break
|
||||
|
||||
case 'MOPIDY_DELETE_PLAYLIST':
|
||||
instruct( socket, store, 'playlists.delete', { uri: action.uri })
|
||||
.then( response => {
|
||||
|
||||
// re-load our global playlists
|
||||
store.dispatch({ type: 'MOPIDY_PLAYLISTS' });
|
||||
// store.dispatch({ type: 'MOPIDY_PLAYLISTS' });
|
||||
});
|
||||
break
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================== ALBUM(S) =============
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
case 'MOPIDY_ALBUMS':
|
||||
store.dispatch({ type: 'MOPIDY_ALBUMS_LOADED', data: false });
|
||||
instruct( socket, store, 'library.browse', { uri: 'local:directory?type=album' } )
|
||||
.then( response => {
|
||||
store.dispatch({ type: 'MOPIDY_ALBUMS_LOADED', data: response });
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_ALBUM':
|
||||
//store.dispatch({ type: 'MOPIDY_ALBUM_LOADED', data: false });
|
||||
@ -526,6 +564,20 @@ const MopidyMiddleware = (function(){
|
||||
})
|
||||
})
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================== ARTIST(S) ============
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
case 'MOPIDY_ARTISTS':
|
||||
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: false });
|
||||
instruct( socket, store, 'library.browse', { uri: 'local:directory?type=artist' } )
|
||||
.then( response => {
|
||||
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: response });
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_ARTIST':
|
||||
store.dispatch({ type: 'MOPIDY_ARTIST_LOADED', data: false });
|
||||
@ -560,6 +612,12 @@ const MopidyMiddleware = (function(){
|
||||
store.dispatch({ type: 'MOPIDY_ARTIST_LOADED', data: artist });
|
||||
})
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================== LOCAL ================
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
case 'MOPIDY_DIRECTORY':
|
||||
store.dispatch({ type: 'MOPIDY_DIRECTORY_LOADED', data: false });
|
||||
@ -569,22 +627,6 @@ const MopidyMiddleware = (function(){
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_ARTISTS':
|
||||
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: false });
|
||||
instruct( socket, store, 'library.browse', { uri: 'local:directory?type=artist' } )
|
||||
.then( response => {
|
||||
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: response });
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_ALBUMS':
|
||||
store.dispatch({ type: 'MOPIDY_ALBUMS_LOADED', data: false });
|
||||
instruct( socket, store, 'library.browse', { uri: 'local:directory?type=album' } )
|
||||
.then( response => {
|
||||
store.dispatch({ type: 'MOPIDY_ALBUMS_LOADED', data: response });
|
||||
})
|
||||
break;
|
||||
|
||||
// This action is irrelevant to us, pass it on to the next middleware
|
||||
default:
|
||||
return next(action);
|
||||
|
||||
@ -262,9 +262,18 @@ export function getFeaturedPlaylists(){
|
||||
|
||||
sendRequest( dispatch, getState, 'browse/featured-playlists?timestamp='+timestamp+'&country='+getState().spotify.country+'&limit=50&locale='+getState().spotify.locale )
|
||||
.then( response => {
|
||||
for (var i = 0; i < response.playlists.items.length; i++){
|
||||
dispatch({
|
||||
type: 'PLAYLIST_LOADED',
|
||||
playlist: response.playlists.items[i]
|
||||
});
|
||||
}
|
||||
dispatch({
|
||||
type: 'SPOTIFY_FEATURED_PLAYLISTS_LOADED',
|
||||
data: response
|
||||
data: {
|
||||
message: response.message,
|
||||
playlists: helpers.asURIs(response.playlists.items)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -290,28 +299,41 @@ export function getCategory( id ){
|
||||
|
||||
dispatch({ type: 'SPOTIFY_CATEGORY_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'browse/categories/'+id+'?country='+getState().spotify.country+'&locale='+getState().spotify.locale )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_CATEGORY_LOADED',
|
||||
data: response
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getCategoryPlaylists( id ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'browse/categories/'+id+'/playlists?limit=50&country='+getState().spotify.country+'&locale='+getState().spotify.locale )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED',
|
||||
data: response.playlists
|
||||
});
|
||||
$.when(
|
||||
|
||||
sendRequest( dispatch, getState, 'browse/categories/'+id+'?country='+getState().spotify.country+'&locale='+getState().spotify.locale ),
|
||||
sendRequest( dispatch, getState, 'browse/categories/'+id+'/playlists?limit=50&country='+getState().spotify.country+'&locale='+getState().spotify.locale )
|
||||
|
||||
).then( ( category_response, playlists_response ) => {
|
||||
|
||||
var playlists = []
|
||||
for (var i = 0; i < playlists_response.playlists.items.length; i++){
|
||||
playlists.push(
|
||||
Object.assign(
|
||||
{},
|
||||
playlists_response.playlists.items[i],
|
||||
{
|
||||
tracks: false,
|
||||
tracks_total: playlists_response.playlists.items[i].tracks.total
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var category = Object.assign(
|
||||
{},
|
||||
category_response,
|
||||
{
|
||||
items: false,
|
||||
playlists: playlists
|
||||
}
|
||||
)
|
||||
|
||||
dispatch({
|
||||
type: 'SPOTIFY_CATEGORY_LOADED',
|
||||
data: category
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,13 +352,14 @@ export function getNewReleases(){
|
||||
}
|
||||
}
|
||||
|
||||
export function getURL( url, action_name ){
|
||||
export function getURL( url, action_name, uri = false ){
|
||||
return (dispatch, getState) => {
|
||||
sendRequest( dispatch, getState, url )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: action_name,
|
||||
data: response
|
||||
data: response,
|
||||
uri: uri
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -774,15 +797,24 @@ export function savePlaylist( uri, name, is_public ){
|
||||
export function getPlaylist( uri ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_PLAYLIST_LOADED', data: false });
|
||||
|
||||
// get the main playlist object
|
||||
sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'?market='+getState().spotify.country )
|
||||
.then( response => {
|
||||
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
response,
|
||||
{
|
||||
can_edit: (getState().spotify.me && response.owner.id == getState().spotify.me.id),
|
||||
tracks: helpers.flattenTracks(response.tracks.items),
|
||||
tracks_more: response.tracks.next,
|
||||
tracks_total: response.tracks.total
|
||||
}
|
||||
)
|
||||
|
||||
dispatch({
|
||||
type: 'SPOTIFY_PLAYLIST_LOADED',
|
||||
data: response
|
||||
type: 'PLAYLIST_LOADED',
|
||||
playlist: playlist
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -801,15 +833,28 @@ function loadNextPlaylistsBatch( dispatch, getState, playlists, lastResponse ){
|
||||
// used to define what we can add tracks to
|
||||
if( getState().spotify.authorized ){
|
||||
for( var i = 0; i < playlists.length; i++ ){
|
||||
if( playlists[i].owner.id == getState().spotify.me.id ){
|
||||
playlists[i] = Object.assign({}, playlists[i], { can_edit: true })
|
||||
}
|
||||
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
playlists[i],
|
||||
{
|
||||
can_edit: (getState().spotify.me && playlists[i].owner.id == getState().spotify.me.id),
|
||||
tracks: helpers.flattenTracks(playlists[i].tracks.items),
|
||||
tracks_more: response.tracks.next,
|
||||
tracks_total: response.tracks.total
|
||||
}
|
||||
)
|
||||
|
||||
dispatch({
|
||||
type: 'PLAYLIST_LOADED',
|
||||
playlist: playlist
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED',
|
||||
data: playlists
|
||||
type: 'LIBRARY_PLAYLISTS_LOADED',
|
||||
uris: helpers.asURIs(playlists)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,46 +231,21 @@ export default function reducer(ui = {}, action){
|
||||
if( !action.data ) return Object.assign({}, ui, { playlist: false })
|
||||
return Object.assign({}, ui, { playlist: action.data })
|
||||
|
||||
case 'SPOTIFY_PLAYLIST_LOADED':
|
||||
if( !action.data ) return Object.assign({}, ui, { playlist: false })
|
||||
case 'PLAYLIST_LOADED_MORE_TRACKS':
|
||||
|
||||
var tracks = []
|
||||
for( var i = 0; i < action.data.tracks.items.length; i++ ){
|
||||
tracks.push( Object.assign(
|
||||
{},
|
||||
action.data.tracks.items[i].track,
|
||||
{
|
||||
added_by: action.data.tracks.items[i].added_by,
|
||||
added_at: action.data.tracks.items[i].added_at
|
||||
}
|
||||
))
|
||||
}
|
||||
var playlists = ui.playlists
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
playlists[action.uri],
|
||||
{
|
||||
tracks: [...playlists[action.uri].tracks, ...helpers.flattenTracks(action.data.items)],
|
||||
tracks_more: action.data.next,
|
||||
tracks_total: action.data.total
|
||||
}
|
||||
)
|
||||
|
||||
var playlist = Object.assign({}, action.data, {
|
||||
tracks: tracks,
|
||||
tracks_more: action.data.tracks.next,
|
||||
tracks_total: action.data.tracks.total
|
||||
})
|
||||
return Object.assign({}, ui, { playlist: playlist });
|
||||
|
||||
case 'SPOTIFY_PLAYLIST_LOADED_MORE':
|
||||
var tracks = []
|
||||
for( var i = 0; i < action.data.items.length; i++ ){
|
||||
tracks.push( Object.assign(
|
||||
{},
|
||||
action.data.items[i].track,
|
||||
{
|
||||
added_by: action.data.items[i].added_by,
|
||||
added_at: action.data.items[i].added_at
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
var playlist = Object.assign({}, ui.playlist, {
|
||||
tracks: [...ui.playlist.tracks, ...tracks],
|
||||
tracks_more: action.data.next
|
||||
})
|
||||
return Object.assign({}, ui, { playlist: playlist });
|
||||
playlists[action.uri] = playlist
|
||||
return Object.assign({}, ui, { playlists: playlists });
|
||||
|
||||
case 'PLAYLIST_TRACKS_REMOVED':
|
||||
var tracks = Object.assign([], ui.playlist.tracks)
|
||||
@ -316,14 +291,25 @@ export default function reducer(ui = {}, action){
|
||||
* Library Playlists
|
||||
**/
|
||||
|
||||
case 'MOPIDY_PLAYLISTS_LOADED':
|
||||
case 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED':
|
||||
if( !action.data ) return ui
|
||||
var playlists = [...ui.playlists, ...action.data]
|
||||
playlists = helpers.mergeDuplicates(playlists, 'uri')
|
||||
helpers.sortItems(playlists, 'name')
|
||||
case 'PLAYLIST_LOADED':
|
||||
case 'PLAYLIST_UPDATED':
|
||||
var playlists = ui.playlists
|
||||
var playlist = Object.assign({}, action.playlist)
|
||||
|
||||
// if we already have one in our list, fetch it and update it
|
||||
if (playlists[action.playlist.uri]){
|
||||
playlist = Object.assign({}, playlists[action.playlist.uri], action.playlist)
|
||||
}
|
||||
|
||||
playlists[action.playlist.uri] = playlist
|
||||
return Object.assign({}, ui, { playlists: playlists });
|
||||
|
||||
case 'LIBRARY_PLAYLISTS_LOADED':
|
||||
var library_playlists = []
|
||||
if (ui.library_playlists) library_playlists = ui.library_playlists
|
||||
|
||||
return Object.assign({}, ui, {
|
||||
playlists: playlists
|
||||
library_playlists: [...library_playlists, ...action.uris]
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ class App extends React.Component{
|
||||
|
||||
// mopidy comes online
|
||||
if( !this.props.mopidy_connected && nextProps.mopidy_connected ){
|
||||
this.props.mopidyActions.getPlaylists();
|
||||
this.props.mopidyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
// spotify authorized
|
||||
|
||||
@ -55,7 +55,7 @@ class Playlist extends React.Component{
|
||||
|
||||
loadMore(){
|
||||
if( !this.props.playlist.tracks_more ) return
|
||||
this.props.spotifyActions.getURL( this.props.playlist.tracks_more, 'SPOTIFY_PLAYLIST_LOADED_MORE' );
|
||||
this.props.spotifyActions.getURL( this.props.playlist.tracks_more, 'PLAYLIST_LOADED_MORE_TRACKS', this.props.playlist.uri );
|
||||
}
|
||||
|
||||
play(){
|
||||
@ -90,19 +90,6 @@ class Playlist extends React.Component{
|
||||
this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, tracks_indexes )
|
||||
}
|
||||
|
||||
isEditable(){
|
||||
if( helpers.uriSource( this.props.playlist.uri ) == 'spotify' ){
|
||||
if( !this.props.spotify_authorized ) return false
|
||||
|
||||
return ( this.props.playlist &&
|
||||
this.props.playlist.owner &&
|
||||
this.props.playlist.owner.id == this.props.spotify_userid
|
||||
)
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
renderExtraButtons(){
|
||||
switch( helpers.uriSource( this.props.playlist.uri ) ){
|
||||
|
||||
@ -115,7 +102,7 @@ class Playlist extends React.Component{
|
||||
)
|
||||
|
||||
case 'spotify':
|
||||
if( this.isEditable() ){
|
||||
if( this.props.playlist.can_edit ){
|
||||
return (
|
||||
<span>
|
||||
<button className="large tertiary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
|
||||
@ -167,7 +154,7 @@ class Playlist extends React.Component{
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.props.playlist.tracks ? <TrackList context={ this.isEditable() ? 'editable-playlist' : 'playlist'} tracks={ this.props.playlist.tracks } removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
|
||||
{ this.props.playlist.tracks ? <TrackList context={ this.props.playlist.can_edit ? 'editable-playlist' : 'playlist'} tracks={ this.props.playlist.tracks } removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
|
||||
<LazyLoadListener loadMore={ () => this.loadMore() }/>
|
||||
</section>
|
||||
|
||||
@ -186,7 +173,7 @@ class Playlist extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
playlist: state.ui.playlist,
|
||||
playlist: state.ui.playlists[ownProps.params.uri],
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
spotify_authorized: state.spotify.authorized,
|
||||
spotify_userid: state.spotify.me.id
|
||||
|
||||
@ -17,13 +17,11 @@ class DiscoverCategory extends React.Component{
|
||||
|
||||
componentDidMount(){
|
||||
this.props.spotifyActions.getCategory( this.props.params.id );
|
||||
this.props.spotifyActions.getCategoryPlaylists( this.props.params.id );
|
||||
}
|
||||
|
||||
componentWillReceiveProps( nextProps ){
|
||||
if( nextProps.params.id != this.props.params.id ){
|
||||
this.props.spotifyActions.getCategory( nextProps.params.id );
|
||||
this.props.spotifyActions.getCategoryPlaylists( nextProps.params.id );
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +37,7 @@ class DiscoverCategory extends React.Component{
|
||||
<div className="view discover-categories-view">
|
||||
<Header icon="grid" title={this.props.spotify.category.name} />
|
||||
<section className="grid-wrapper">
|
||||
{ this.props.spotify.category_playlists ? <PlaylistGrid playlists={this.props.spotify.category_playlists.items} /> : null }
|
||||
{ this.props.spotify.category.playlists ? <PlaylistGrid playlists={this.props.spotify.category.playlists} /> : null }
|
||||
</section>
|
||||
<LazyLoadListener loadMore={ () => this.loadMore() }/>
|
||||
</div>
|
||||
|
||||
@ -20,11 +20,22 @@ class DiscoverFeatured extends React.Component{
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
var playlists = []
|
||||
if (this.props.featured_playlists){
|
||||
for (var i = 0; i < this.props.featured_playlists.playlists.length; i++){
|
||||
var uri = this.props.featured_playlists.playlists[i]
|
||||
if (this.props.playlists.hasOwnProperty(uri)){
|
||||
playlists.push(this.props.playlists[uri])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="view discover-featured-view">
|
||||
<Header icon="star" title="Featured playlists" />
|
||||
<section className="grid-wrapper">
|
||||
{ this.props.spotify.featured_playlists ? <PlaylistGrid playlists={this.props.spotify.featured_playlists.playlists.items} /> : null }
|
||||
{ playlists ? <PlaylistGrid playlists={playlists} /> : null }
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
@ -39,7 +50,10 @@ class DiscoverFeatured extends React.Component{
|
||||
**/
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return state;
|
||||
return {
|
||||
featured_playlists: state.spotify.featured_playlists,
|
||||
playlists: state.ui.playlists
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
|
||||
@ -33,9 +33,16 @@ class LibraryPlaylists extends React.Component{
|
||||
}
|
||||
|
||||
renderView(){
|
||||
if( !this.props.playlists ) return null
|
||||
if( !this.props.library_playlists || !this.props.playlists ) return null
|
||||
|
||||
var playlists = []
|
||||
for (var i = 0; i < this.props.library_playlists.length; i++){
|
||||
var uri = this.props.library_playlists[i]
|
||||
if (this.props.playlists.hasOwnProperty(uri)){
|
||||
playlists.push(this.props.playlists[uri])
|
||||
}
|
||||
}
|
||||
|
||||
var playlists = Object.assign([], this.props.playlists)
|
||||
if( this.props.sort ){
|
||||
playlists = helpers.sortItems(playlists, this.props.sort, this.props.sort_reverse)
|
||||
}
|
||||
@ -141,6 +148,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
view: state.ui.library_playlists_view,
|
||||
sort: state.ui.library_playlists_sort,
|
||||
sort_reverse: state.ui.library_playlists_sort_reverse,
|
||||
library_playlists: state.ui.library_playlists,
|
||||
playlists: state.ui.playlists
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user