diff --git a/src/js/bootstrap.js b/src/js/bootstrap.js index 78c3b107..3cb7f535 100755 --- a/src/js/bootstrap.js +++ b/src/js/bootstrap.js @@ -63,7 +63,8 @@ var initialState = { albums: [], playlists: [], tracks: [] - } + }, + playlists: [] } }; diff --git a/src/js/components/Track.js b/src/js/components/Track.js index 1ec5610f..8e6fe59f 100755 --- a/src/js/components/Track.js +++ b/src/js/components/Track.js @@ -49,13 +49,13 @@ export default class Track extends React.Component{ onContextMenu={ (e) => this.handleContextMenu(e) }> { this.props.track.selected ? : null } - {track.name} + { track.name ? track.name : '-' } - { track.artists ? : null } + { track.artists ? : '-' } - { track.album ? : null } + { track.album ? : '-' } { track.duration_ms ? : null } diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 385c6b83..40500b9c 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -206,8 +206,8 @@ const MopidyMiddleware = (function(){ }, response, { - tracks: response.tracks, - total_tracks: response.tracks.length + tracks: ( response.tracks ? response.tracks : [] ), + tracks_total: ( response.tracks ? response.tracks.length : 0 ) } ) @@ -223,17 +223,19 @@ const MopidyMiddleware = (function(){ if (response.hasOwnProperty(uri)) { var track = response[uri][0]; - - // find the track reference, and drop in the full track data - function getByURI( trackReference ){ - return track.uri == trackReference.uri - } - var trackReferences = playlist.tracks.filter(getByURI); - - // there could be multiple instances of this track, so accommodate this - for( var j = 0; j < trackReferences.length; j++){ - var key = playlist.tracks.indexOf( trackReferences[j] ); - playlist.tracks[ key ] = track; + if( track ){ + + // find the track reference, and drop in the full track data + function getByURI( trackReference ){ + return track.uri == trackReference.uri + } + var trackReferences = playlist.tracks.filter(getByURI); + + // there could be multiple instances of this track, so accommodate this + for( var j = 0; j < trackReferences.length; j++){ + var key = playlist.tracks.indexOf( trackReferences[j] ); + playlist.tracks[ key ] = track; + } } } } diff --git a/src/js/services/mopidy/reducer.js b/src/js/services/mopidy/reducer.js index 225b2ced..d1d1837a 100755 --- a/src/js/services/mopidy/reducer.js +++ b/src/js/services/mopidy/reducer.js @@ -67,10 +67,6 @@ export default function reducer(mopidy = {}, action){ * Asset-oriented actions **/ - case 'MOPIDY_PLAYLISTS_LOADED': - if( !action.data ) return mopidy; - return Object.assign({}, mopidy, { playlists: action.data }); - case 'MOPIDY_DIRECTORY_LOADED': return Object.assign({}, mopidy, { directory: action.data diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 7fb65692..15345f6b 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -345,18 +345,29 @@ export function getPlaylist( uri ){ } } +function loadNextPlaylistsBatch( dispatch, getState, playlists, lastResponse ){ + if( lastResponse.next ){ + sendRequest( dispatch, getState, lastResponse.next ) + .then( response => { + playlists = [...playlists, ...response.items] + loadNextPlaylistsBatch( dispatch, getState, playlists, response ) + }); + }else{ + dispatch({ + type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED', + data: playlists + }); + } +} -export function getLibraryPlaylists(){ +export function getAllLibraryPlaylists(){ return (dispatch, getState) => { dispatch({ type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED', data: false }); - sendRequest( dispatch, getState, 'me/playlists' ) + sendRequest( dispatch, getState, 'me/playlists?limit=50' ) .then( response => { - dispatch({ - type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED', - data: response - }); + loadNextPlaylistsBatch( dispatch, getState, response.items, response ) }); } } diff --git a/src/js/services/spotify/reducer.js b/src/js/services/spotify/reducer.js index 32701cd7..b354738a 100755 --- a/src/js/services/spotify/reducer.js +++ b/src/js/services/spotify/reducer.js @@ -58,9 +58,6 @@ export default function reducer(spotify = {}, action){ case 'SPOTIFY_ARTISTS_LOADED': return Object.assign({}, spotify, { artists: action.data }); - case 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED': - return Object.assign({}, spotify, { library_playlists: action.data }); - case 'SPOTIFY_LIBRARY_ARTISTS_LOADED': return Object.assign({}, spotify, { library_artists: action.data }); diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index a47630be..21828e0d 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -132,6 +132,23 @@ export default function reducer(ui = {}, action){ return Object.assign({}, ui, { playlist: playlist }); + /** + * Library Playlists + **/ + + case 'MOPIDY_PLAYLISTS_LOADED': + if( !action.data ) return ui + return Object.assign({}, ui, { + playlists: [...ui.playlists, ...action.data], + }); + + case 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED': + if( !action.data ) return ui + return Object.assign({}, ui, { + playlists: [...ui.playlists, ...action.data] + }); + + /** * Current track and tracklist diff --git a/src/js/views/library/LibraryPlaylists.js b/src/js/views/library/LibraryPlaylists.js index 0703b03c..013b06fb 100755 --- a/src/js/views/library/LibraryPlaylists.js +++ b/src/js/views/library/LibraryPlaylists.js @@ -18,59 +18,26 @@ class LibraryPlaylists extends React.Component{ // on render componentDidMount(){ - if( this.props.mopidy.connected ){ - this.props.mopidyActions.getPlaylists(); - } - if( this.props.spotify.authorized ){ - this.props.spotifyActions.getLibraryPlaylists(); - } + if( this.props.mopidy_connected ) this.props.mopidyActions.getPlaylists(); + if( this.props.spotify_authorized ) this.props.spotifyActions.getAllLibraryPlaylists(); } - componentWillReceiveProps( nextProps ){ - if( !this.props.mopidy.connected && nextProps.mopidy.connected ){ - this.props.mopidyActions.getPlaylists(); - } - if( !this.props.spotify.authorized && nextProps.spotify.authorized ){ - this.props.spotifyActions.getLibraryPlaylists(); - } - } - - compiledPlaylistSources(){ - var playlists = []; - - if( this.props.mopidy.playlists ){ - playlists = [...playlists, ...this.props.mopidy.playlists] - } - - if( this.props.spotify.library_playlists ){ - playlists = [...playlists, ...this.props.spotify.library_playlists.items] - } - - return playlists; - } - - renderPlaylists(){ - var playlists = this.compiledPlaylistSources() - if( !playlists ) return null - + render(){ + if( !this.props.playlists ) return null var columns = [ { name: 'name', width: '50'}, { name: 'uri', width: '25'} ] - return - } - - render(){ return (
-
+ +
+
- { this.renderPlaylists() } +
+
) } @@ -84,7 +51,12 @@ class LibraryPlaylists extends React.Component{ **/ const mapStateToProps = (state, ownProps) => { - return state; + return { + playlists: state.ui.playlists, + playlists_more: state.ui.playlists_more, + mopidy_connected: state.mopidy.connected, + spotify_authorized: state.spotify.authorized + } } const mapDispatchToProps = (dispatch) => { diff --git a/src/scss/global/_forms.scss b/src/scss/global/_forms.scss index bd680701..5db4da43 100755 --- a/src/scss/global/_forms.scss +++ b/src/scss/global/_forms.scss @@ -96,7 +96,7 @@ label { } .text { - display: inline-block; + display: block; padding: 10px 14px; } }