diff --git a/src/js/components/Track.js b/src/js/components/Track.js index 2c802560..e4a1a81e 100755 --- a/src/js/components/Track.js +++ b/src/js/components/Track.js @@ -12,21 +12,15 @@ export default class Track extends React.Component{ super(props); } - handleClick(e){ - var target = $(e.target); - if( !target.is('a') && target.closest('a').length <= 0 ){ - this.props.handleClick(e); - } - } - handleDoubleClick(e){ return this.props.handleDoubleClick(e); } handleMouseDown(e){ - // if we're not selected, perform click behavior [first] << this is assumed - if( !this.props.track.selected ) this.handleClick(e) - this.props.handleMouseDown(e) + var target = $(e.target); + if( !target.is('a') && target.closest('a').length <= 0 ){ + this.props.handleMouseDown(e); + } } handleMouseUp(e){ @@ -35,11 +29,6 @@ export default class Track extends React.Component{ handleContextMenu(e){ e.preventDefault(); - - // trigger a regular click event - if( !this.props.track.selected ) this.handleClick(e); - - // notify our tracklist this.props.handleContextMenu(e); } @@ -56,12 +45,11 @@ export default class Track extends React.Component{ className={className} onMouseDown={ e => this.handleMouseDown(e) } onMouseUp={ e => this.handleMouseUp(e) } - onClick={ e => this.handleClick(e) } onDoubleClick={ e => this.handleDoubleClick(e) } onContextMenu={ e => this.handleContextMenu(e) }> { this.props.track.selected ? : null } - { track.name ? track.name : track.uri } + { track.name ? track.name : {track.uri} } { track.artists ? : '-' } diff --git a/src/js/components/TrackList.js b/src/js/components/TrackList.js index edc28637..f32321ca 100755 --- a/src/js/components/TrackList.js +++ b/src/js/components/TrackList.js @@ -48,9 +48,55 @@ class TrackList extends React.Component{ } } - handleClick( e, index ){ + handleDoubleClick(e, index){ + if( this.props.context_menu.show ) this.props.uiActions.hideContextMenu() + this.playTracks() + } + + handleMouseDown(e, index){ if( this.props.context_menu.show ) this.props.uiActions.hideContextMenu() + if( !this.state.tracks[index].selected && !this.isRightClick(e) && !e.ctrlKey ) this.toggleTrackSelections(e, index) + + var selected_tracks = this.selectedTracks() + this.props.uiActions.dragStart( e, this.props.context, selected_tracks, this.tracksIndexes(selected_tracks) ) + } + + handleMouseUp(e, index){ + + // right-clicking on an un-highlighted track + if( !this.state.tracks[index].selected && this.isRightClick(e) ){ + this.toggleTrackSelections(e, index) + + // selected track, regular click + }else if( this.state.tracks[index].selected && !this.isRightClick(e) ){ + this.toggleTrackSelections(e, index) + + // ctrl key + }else if( e.ctrlKey ){ + this.toggleTrackSelections(e, index) + } + + if( this.props.dragger && this.props.dragger.active ){ + + // 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 ); + } + } + } + + handleContextMenu(e, index){ + var selected_tracks = this.selectedTracks() + var data = { + selected_tracks: selected_tracks, + selected_tracks_indexes: this.tracksIndexes( selected_tracks ) + } + this.props.uiActions.showContextMenu( e, this.props.context, data ) + } + + toggleTrackSelections(e, index){ var tracks = this.state.tracks if( e.ctrlKey ){ @@ -83,34 +129,12 @@ class TrackList extends React.Component{ this.setState({ tracks: tracks, lastSelectedTrack: index }) } - handleDoubleClick(e, index){ - if( this.props.context_menu.show ) this.props.uiActions.hideContextMenu() - this.playTracks() - } - - handleMouseDown(e, index){ - var selected_tracks = this.selectedTracks() - this.props.uiActions.dragStart( e, this.props.context, selected_tracks, this.tracksIndexes(selected_tracks) ) - } - - handleMouseUp(e, index){ - if( this.props.dragger && this.props.dragger.active ){ - - // 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 ); - } - } - } - - handleContextMenu(e, index){ - var selected_tracks = this.selectedTracks() - var data = { - selected_tracks: selected_tracks, - selected_tracks_indexes: this.tracksIndexes( selected_tracks ) - } - this.props.uiActions.showContextMenu( e, this.props.context, data ) + isRightClick(e){ + if( 'which' in e ) + return e.which == 3 + if( 'button' in e ) + return e.button == 2 + return false } keyifyTracks( tracks ){ diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 71932e75..210ce621 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -12,7 +12,10 @@ 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) + var actions_to_log = null + //actions_to_log = 'SPOTIFY' + //actions_to_log = 'MOPIDY' + if( action.type.startsWith(actions_to_log) ) console.log(action) switch( action.type ){ diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 8ce77ca7..3b28efbc 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -210,6 +210,15 @@ 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_PLAYLISTS' }); + }); + break + case 'MOPIDY_PLAYLIST': store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: false }); instruct( socket, store, 'playlists.lookup', action.data ) @@ -227,13 +236,13 @@ const MopidyMiddleware = (function(){ ) // tracks? get the full track objects - if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_FETCH_PLAYLIST_TRACKS', tracks: playlist.tracks }) + if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_PLAYLIST_TRACKS', tracks: playlist.tracks }) store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: playlist }) }) break; - case 'MOPIDY_FETCH_PLAYLIST_TRACKS': + case 'MOPIDY_PLAYLIST_TRACKS': var tracks = Object.assign([], action.tracks) var uris = []; for( var i = 0; i < tracks.length; i++ ){ @@ -315,15 +324,6 @@ 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_PLAYLISTS' }); - }); - break - case 'MOPIDY_SAVE_PLAYLIST': instruct( socket, store, 'playlists.lookup', { uri: action.uri }) .then( response => { @@ -376,7 +376,7 @@ const MopidyMiddleware = (function(){ .then( response => { // and now re-render our full track references - store.dispatch({ type: 'MOPIDY_FETCH_PLAYLIST_TRACKS', tracks: playlist.tracks }) + store.dispatch({ type: 'MOPIDY_PLAYLIST_TRACKS', tracks: playlist.tracks }) }) }); break diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index b55d2e85..a15288e7 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -641,3 +641,20 @@ export function deleteTracksFromPlaylist( uri, snapshot_id, tracks_indexes ){ } } +export function reorderPlaylistTracks( uri, indexes, to_index, snapshot_id ){ + var range_start = indexes[0] + var range_length = indexes.length + return (dispatch, getState) => { + sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) + '/playlists/'+ helpers.getFromUri('playlistid',uri) + '/tracks', 'PUT', { uri: uri, range_start: range_start, range_length: range_length, insert_before: to_index, snapshot_id: snapshot_id } ) + .then( response => { + dispatch({ + type: 'PLAYLIST_TRACKS_REORDERED', + range_start: range_start, + range_length: range_length, + to_index: to_index, + snapshot_id: response.snapshot_id + }); + }); + } +} + diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index 6960dc9c..26a72bb4 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -52,6 +52,16 @@ const SpotifyMiddleware = (function(){ break + case 'SPOTIFY_REORDER_PLAYLIST_TRACKS': + + if( !store.getState().spotify.authorized ){ + alert('Must be logged in to Spotify to do this') + return + } + store.dispatch( actions.reorderPlaylistTracks( action.uri, action.indexes, action.to_index )) + break + + case 'SPOTIFY_SAVE_PLAYLIST': if( !store.getState().spotify.authorized ){ diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js index 067cc292..d00b996a 100755 --- a/src/js/services/ui/actions.js +++ b/src/js/services/ui/actions.js @@ -59,15 +59,17 @@ export function dragEnd(){ return { type: 'DRAG_END' } } -export function reorderPlaylistTracks( uri, indexes, to_index ){ +export function reorderPlaylistTracks( uri, indexes, to_index, snapshot_id = false ){ switch( helpers.uriSource( uri ) ){ case 'spotify': + // TODO: handle bunched selected tracks (ie non-continuious indexes) return { type: 'SPOTIFY_REORDER_PLAYLIST_TRACKS', uri: uri, indexes: indexes, - to_index: to_index + to_index: to_index, + snapshot_id: snapshot_id } case 'm3u': diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index 645af616..11a9fa96 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -233,13 +233,13 @@ export default function reducer(ui = {}, action){ 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 diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index 6d35feeb..f16fdfd1 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -74,7 +74,7 @@ class Playlist extends React.Component{ } reorderTracks( indexes, index ){ - this.props.uiActions.reorderPlaylistTracks( this.props.playlist.uri, indexes, index ) + this.props.uiActions.reorderPlaylistTracks( this.props.playlist.uri, indexes, index, this.props.playlist.snapshot_id ) } removeTracks( tracks_indexes ){