Playlists library; Local playlist loading dud tracks
This commit is contained in:
3
src/js/bootstrap.js
vendored
3
src/js/bootstrap.js
vendored
@ -63,7 +63,8 @@ var initialState = {
|
||||
albums: [],
|
||||
playlists: [],
|
||||
tracks: []
|
||||
}
|
||||
},
|
||||
playlists: []
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -49,13 +49,13 @@ export default class Track extends React.Component{
|
||||
onContextMenu={ (e) => this.handleContextMenu(e) }>
|
||||
{ this.props.track.selected ? <FontAwesome name="check" className="select-state" fixedWidth /> : null }
|
||||
<span className="col name">
|
||||
{track.name}
|
||||
{ track.name ? track.name : '-' }
|
||||
</span>
|
||||
<span className="col artists">
|
||||
{ track.artists ? <ArtistSentence artists={track.artists} /> : null }
|
||||
{ track.artists ? <ArtistSentence artists={track.artists} /> : '-' }
|
||||
</span>
|
||||
<span className="col album">
|
||||
{ track.album ? <AlbumLink album={track.album} /> : null }
|
||||
{ track.album ? <AlbumLink album={track.album} /> : '-' }
|
||||
</span>
|
||||
<span className="col duration">
|
||||
{ track.duration_ms ? <Dater type="length" data={track.duration_ms} /> : null }
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 )
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 });
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 <List columns={columns} rows={playlists} link_prefix="/playlist/" />
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="view library-playlists-view">
|
||||
<Header
|
||||
icon="playlist"
|
||||
title="My playlists"
|
||||
/>
|
||||
|
||||
<Header icon="playlist" title="My playlists" />
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.renderPlaylists() }
|
||||
<List columns={columns} rows={this.props.playlists} link_prefix="/playlist/" />
|
||||
</section>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -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) => {
|
||||
|
||||
@ -96,7 +96,7 @@ label {
|
||||
}
|
||||
|
||||
.text {
|
||||
display: inline-block;
|
||||
display: block;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user