Reordering local playlist tracks; Lazy-loading track details

This commit is contained in:
James Barnsley
2016-11-16 13:13:35 +13:00
parent af32551ddf
commit 98770441cc
8 changed files with 123 additions and 59 deletions

View File

@ -61,7 +61,7 @@ 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 ? track.name : track.uri }
</span>
<span className="col artists">
{ track.artists ? <ArtistSentence artists={track.artists} /> : '-' }

View File

@ -95,8 +95,12 @@ class TrackList extends React.Component{
handleMouseUp(e, index){
if( this.props.dragger && this.props.dragger.active ){
var indexes = this.props.dragger.victims_indexes
this.props.uiActions.reorderTracks(this.props.context, indexes, index)
// if this tracklist handles sorting, handle it
if( typeof(this.props.reorderTracks) !== 'undefined' ){
var indexes = this.props.dragger.victims_indexes
return this.props.reorderTracks( indexes, index );
}
}
}

View File

@ -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 ){

View File

@ -225,48 +225,48 @@ const MopidyMiddleware = (function(){
tracks_total: ( response.tracks ? response.tracks.length : 0 )
}
)
var uris = [];
for( var i = 0; i < playlist.tracks.length; i++ ){
uris.push( playlist.tracks[i].uri );
}
// no tracks
if( uris.length <= 0 ){
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: playlist });
// tracks? get the full track objects
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_FETCH_PLAYLIST_TRACKS', tracks: playlist.tracks })
// tracks? let's flesh them out with full track objects, rather than just reference objects
}else{
instruct( socket, store, 'library.lookup', { uris: uris } )
.then( response => {
for(var uri in response){
if (response.hasOwnProperty(uri)) {
var track = response[uri][0];
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;
}
}
}
}
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: playlist });
})
}
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: playlist })
})
break;
case 'MOPIDY_FETCH_PLAYLIST_TRACKS':
var tracks = Object.assign([], action.tracks)
var uris = [];
for( var i = 0; i < tracks.length; i++ ){
uris.push( tracks[i].uri );
}
instruct( socket, store, 'library.lookup', { uris: uris } )
.then( response => {
for(var uri in response){
if (response.hasOwnProperty(uri)) {
var track = response[uri][0]
if( track ){
// find the track reference, and drop in the full track data
function getByURI( trackReference ){
return track.uri == trackReference.uri
}
var trackReferences = tracks.filter(getByURI);
// there could be multiple instances of this track, so accommodate this
for( var j = 0; j < trackReferences.length; j++){
var key = tracks.indexOf( trackReferences[j] );
tracks[ key ] = track;
}
}
}
}
store.dispatch({ type: 'PLAYLIST_TRACKS_LOADED', tracks: tracks })
})
break
case 'MOPIDY_ADD_PLAYLIST_TRACKS':
instruct( socket, store, 'playlists.lookup', { uri: action.playlist_uri })
@ -339,6 +339,48 @@ const MopidyMiddleware = (function(){
});
break
case 'MOPIDY_REORDER_PLAYLIST_TRACKS':
instruct( socket, store, 'playlists.lookup', { uri: action.uri })
.then( response => {
var playlist = Object.assign({}, response)
var tracks = Object.assign([], playlist.tracks)
var tracks_to_move = []
// calculate destination index: if dragging down, accommodate the offset created by the tracks we're moving
var to_index = action.to_index
var indexes = action.indexes
var range_start = indexes[0]
var range_length = indexes.length
if( to_index > range_start ) to_index = to_index - range_length
// collate our tracks to be moved
for( var i = 0; i < indexes.length; i++ ){
// add to FRONT: we work backwards to avoid screwing up our indexes
tracks_to_move.unshift( tracks[indexes[i]] )
}
// remove tracks from their old location
// BIG ASSUMPTION: this is one continuious set of indexes, ie not 1,2,5,6,9
tracks.splice( range_start, range_length )
// now plug them back in, in their new location
for( var i = 0; i < tracks_to_move.length; i++ ){
tracks.splice( to_index, 0, tracks_to_move[i] )
}
// update playlist
playlist = Object.assign({}, playlist, { tracks: tracks })
instruct( socket, store, 'playlists.save', { playlist: playlist } )
.then( response => {
// and now re-render our full track references
store.dispatch({ type: 'MOPIDY_FETCH_PLAYLIST_TRACKS', tracks: playlist.tracks })
})
});
break
case 'MOPIDY_DELETE_PLAYLIST':
instruct( socket, store, 'playlists.delete', { uri: action.uri })
.then( response => {

View File

@ -59,22 +59,23 @@ export function dragEnd(){
return { type: 'DRAG_END' }
}
export function reorderTracks( context, indexes, destination_index ){
console.log('uiActions.reorderTracks', context, indexes, destination_index)
switch( context ){
export function reorderPlaylistTracks( uri, indexes, to_index ){
switch( helpers.uriSource( uri ) ){
case 'queue':
case 'spotify':
return {
type: 'MOPIDY_REORDER_TRACKLIST',
type: 'SPOTIFY_REORDER_PLAYLIST_TRACKS',
uri: uri,
indexes: indexes,
destination_index: destination_index
to_index: to_index
}
case 'editable-playlist':
case 'm3u':
return {
type: 'SPOTIFY_REORDER_TRACKLIST',
type: 'MOPIDY_REORDER_PLAYLIST_TRACKS',
uri: uri,
indexes: indexes,
destination_index: destination_index
to_index: to_index
}
}
}

View File

@ -221,20 +221,28 @@ export default function reducer(ui = {}, action){
case 'PLAYLIST_TRACKS_REMOVED':
var tracks = Object.assign([], ui.playlist.tracks)
for( var i = 0; i < action.tracks_indexes.length; i++ ){
tracks.splice( action.tracks_indexes[i], 1 )
var indexes = action.tracks_indexes.reverse()
for( var i = 0; i < indexes.length; i++ ){
tracks.splice( indexes[i], 1 )
}
var snapshot_id = null
if( action.snapshot_id ) snapshot_id = action.snapshot_id
var playlist = Object.assign({}, ui.playlist, { tracks: tracks, snapshot_id: snapshot_id })
return Object.assign({}, ui, { playlist: playlist });
case 'PLAYLIST_TRACKS_LOADED':
var playlist = Object.assign({}, ui.playlist, { tracks: action.tracks })
return Object.assign({}, ui, { playlist: playlist });
case 'PLAYLIST_TRACKS_REORDERED':
var snapshot_id = null
if( action.snapshot_id ) snapshot_id = action.snapshot_id
var playlist = Object.assign({}, ui.playlist, { tracks: action.tracks, snapshot_id: snapshot_id })
return Object.assign({}, ui, { playlist: playlist });
/**
* Library Playlists
*
* TODO: Map sources and merge any replicated URIS
*
**/
case 'MOPIDY_PLAYLISTS_LOADED':

View File

@ -73,8 +73,12 @@ class Playlist extends React.Component{
this.props.mopidyActions.deletePlaylist( this.props.params.uri )
}
removeTracks( track_indexes ){
this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, track_indexes )
reorderTracks( indexes, index ){
this.props.uiActions.reorderPlaylistTracks( this.props.playlist.uri, indexes, index )
}
removeTracks( tracks_indexes ){
this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, tracks_indexes )
}
renderEditButtons(){
@ -138,7 +142,7 @@ class Playlist extends React.Component{
</div>
<section className="list-wrapper">
{ this.props.playlist.tracks ? <TrackList context="editable-playlist" tracks={ this.props.playlist.tracks } removeTracks={ track_indexes => this.removeTracks(track_indexes) } /> : null }
{ this.props.playlist.tracks ? <TrackList context="editable-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>

View File

@ -37,6 +37,10 @@ class Queue extends React.Component{
this.props.mopidyActions.changeTrack( tracks[0].tlid )
}
reorderTracks( indexes, index ){
this.props.mopidyActions.reorderTracklist( indexes, index )
}
render(){
return (
<div className="view queue-view">
@ -50,7 +54,8 @@ class Queue extends React.Component{
tracks={this.props.current_tracklist}
removeTracks={ tracks => this.removeTracks( tracks ) }
playTracks={ tracks => this.playTracks( tracks ) }
playTrack={ track => this.playTrack( track ) } />
playTrack={ track => this.playTrack( track ) }
reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } />
</section>
</div>