From 003b1d6569b0ce1b383bd5a8bf89637d5a84e2ac Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sun, 13 Nov 2016 12:55:00 +1300 Subject: [PATCH] Removing tracks from spotify AND mopidy playlists --- src/js/components/ContextMenu.js | 3 +- src/js/services/mopidy/middleware.js | 22 ++++++++++++ src/js/services/spotify/actions.js | 8 ++--- src/js/services/spotify/middleware.js | 15 ++++++++ src/js/services/ui/actions.js | 51 ++++++++++++++++++++++----- src/js/services/ui/middleware.js | 25 ------------- src/js/services/ui/reducer.js | 10 +++--- src/js/views/Playlist.js | 2 +- 8 files changed, 93 insertions(+), 43 deletions(-) diff --git a/src/js/components/ContextMenu.js b/src/js/components/ContextMenu.js index c2d9002e..9e928ec7 100755 --- a/src/js/components/ContextMenu.js +++ b/src/js/components/ContextMenu.js @@ -161,7 +161,7 @@ class ContextMenu extends React.Component{ } removeFromPlaylist(){ - this.props.uiActions.removeTracksFromPlaylist( this.props.context_menu.data.selected_tracks_indexes ) + this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, this.props.context_menu.data.selected_tracks_indexes ) this.props.uiActions.hideContextMenu(); } @@ -186,6 +186,7 @@ const mapStateToProps = (state, ownProps) => { context_menu: state.ui.context_menu, current_track: state.ui.current_track, current_tracklist: state.ui.current_tracklist, + playlist: state.ui.playlist, playlists: state.ui.playlists } } diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 352a67c2..2a65c572 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -248,6 +248,28 @@ const MopidyMiddleware = (function(){ }) break; + case 'MOPIDY_REMOVE_PLAYLIST_TRACKS': + + // reverse order our indexes (otherwise removing from top will affect the keys following) + function descending(a,b){ + return b-a; + } + var indexes = Object.assign([], action.tracks_indexes) + indexes.sort(descending); + + instruct( socket, store, 'playlists.lookup', { uri: action.playlist_uri }) + .then( response => { + var playlist = Object.assign({}, response) + for( var i = 0; i < indexes.length; i++ ){ + playlist.tracks.splice(indexes[i], 1); + } + instruct( socket, store, 'playlists.save', { playlist: playlist } ) + .then( response => { + store.dispatch({ type: 'PLAYLIST_TRACKS_REMOVED', tracks_indexes: action.tracks_indexes }); + }) + }); + break + case 'MOPIDY_ALBUM': //store.dispatch({ type: 'MOPIDY_ALBUM_LOADED', data: false }); instruct( socket, store, 'library.lookup', action.data ) diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index e5532bf6..830925f2 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -588,13 +588,13 @@ export function toggleFollowingPlaylist( uri, method ){ } } -export function deleteTracksFromPlaylist( uri, snapshot_id, positions ){ +export function deleteTracksFromPlaylist( uri, snapshot_id, tracks_indexes ){ return (dispatch, getState) => { - sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) + '/playlists/'+ helpers.getFromUri('playlistid',uri) + '/tracks', 'DELETE', { snapshot_id: snapshot_id, positions: positions } ) + sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) + '/playlists/'+ helpers.getFromUri('playlistid',uri) + '/tracks', 'DELETE', { snapshot_id: snapshot_id, positions: tracks_indexes } ) .then( response => { dispatch({ - type: 'SPOTIFY_PLAYLIST_TRACKS_REMOVED', - positions: positions, + type: 'PLAYLIST_TRACKS_REMOVED', + tracks_indexes: tracks_indexes, snapshot_id: response.snapshot_id }); }); diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index 66a37d89..02a0d1e8 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -15,6 +15,21 @@ const SpotifyMiddleware = (function(){ case 'SPOTIFY_CONNECT': store.dispatch( actions.getMe() ) + + case 'SPOTIFY_REMOVE_PLAYLIST_TRACKS': + var playlist = state.ui.playlist + + if( !store.getState().spotify.authorized ){ + alert('Must be logged in to Spotify to do this') + return + } + if( !store.getState().spotify.me || store.getState().spotify.me.id != playlist.owner.id ){ + alert('You can only modify tracks you own') + return + } + store.dispatch( actions.deleteTracksFromPlaylist( playlist.uri, playlist.snapshot_id, action.tracks_indexes )) + break + // when our mopidy server current track changes case 'MOPIDY_CURRENTTLTRACK': diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js index c5f78aaa..6cb05f29 100755 --- a/src/js/services/ui/actions.js +++ b/src/js/services/ui/actions.js @@ -1,4 +1,5 @@ +import * as helpers from '../../helpers' export function showContextMenu( e, context = false, data ){ return { @@ -65,18 +66,52 @@ export function dragEnd(){ return { type: 'DRAG_END' } } -export function removeTracksFromPlaylist( track_indexes ){ - return { - type: 'REMOVE_TRACKS_FROM_PLAYLIST', - track_indexes: track_indexes +export function removeTracksFromPlaylist( playlist_uri, tracks_indexes ){ + switch( helpers.uriSource( playlist_uri ) ){ + + case 'spotify': + return { + type: 'SPOTIFY_REMOVE_PLAYLIST_TRACKS', + playlist_uri: playlist_uri, + tracks_indexes: tracks_indexes + } + + case 'm3u': + return { + type: 'MOPIDY_REMOVE_PLAYLIST_TRACKS', + playlist_uri: playlist_uri, + tracks_indexes: tracks_indexes + } + + defaut: + return ui } } export function addTracksToPlaylist( playlist_uri, tracks ){ - return { - type: 'ADD_TRACKS_TO_PLAYLIST', - playlist_uri: playlist_uri, - tracks: tracks + + var tracks_uris = [] + for( var i = 0; i < tracks.length; i++ ){ + tracks_uris.push( tracks[i].uri ) + } + + switch( helpers.uriSource( playlist_uri ) ){ + + case 'spotify': + return { + type: 'SPOTIFY_ADD_PLAYLIST_TRACKS', + playlist_uri: playlist_uri, + tracks_uris: tracks_uris + } + break; + + case 'm3u': + return { + type: 'MOPIDY_ADD_TRACKS_TO_PLAYLIST', + playlist_uri: playlist_uri, + tracks_uris: tracks_uris + } + break; } } diff --git a/src/js/services/ui/middleware.js b/src/js/services/ui/middleware.js index fdd07c3a..5a7a5bb3 100755 --- a/src/js/services/ui/middleware.js +++ b/src/js/services/ui/middleware.js @@ -14,31 +14,6 @@ const UIMiddleware = (function(){ switch(action.type){ - case 'REMOVE_TRACKS_FROM_PLAYLIST': - var playlist = store.getState().ui.playlist - switch( helpers.uriSource( playlist.uri ) ){ - - case 'spotify': - if( !store.getState().spotify.authorized ){ - alert('Must be logged in to Spotify to do this') - return - } - if( !store.getState().spotify.me || store.getState().spotify.me.id != playlist.owner.id ){ - alert('You can only modify tracks you own') - return - } - store.dispatch( spotifyActions.deleteTracksFromPlaylist( playlist.uri, playlist.snapshot_id, action.track_indexes )) - break - - case 'm3u': - alert('TODO: delete from M3U') - break - } - - case 'ADD_TRACKS_TO_PLAYLIST': - console.log(action) - break - // This action is irrelevant to us, pass it on to the next middleware default: return next(action); diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index 67804e9f..36e9cb57 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -227,12 +227,14 @@ export default function reducer(ui = {}, action){ var playlist = Object.assign({}, ui.playlist, { following: action.data }) return Object.assign({}, ui, { playlist: playlist }); - case 'SPOTIFY_PLAYLIST_TRACKS_REMOVED': + case 'PLAYLIST_TRACKS_REMOVED': var tracks = Object.assign([], ui.playlist.tracks) - for( var i = 0; i < action.positions.length; i++ ){ - tracks.splice( action.positions[i], 1 ) + for( var i = 0; i < action.tracks_indexes.length; i++ ){ + tracks.splice( action.tracks_indexes[i], 1 ) } - var playlist = Object.assign({}, ui.playlist, action.snapshot_id, { tracks: tracks }) + 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 }); diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index 202f0954..3f6edbf7 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -71,7 +71,7 @@ class Playlist extends React.Component{ } removeTracks( track_indexes ){ - this.props.uiActions.removeTracksFromPlaylist( track_indexes ) + this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, track_indexes ) } renderFollowOrDeleteButton(){