diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index f2ef18e2..868ef3b1 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -14,7 +14,7 @@ const localstorageMiddleware = (function(){ window._store = store var actions_to_log = null //actions_to_log = 'SPOTIFY' - actions_to_log = 'MOPIDY' + //actions_to_log = 'MOPIDY' if( action.type.startsWith(actions_to_log) ) console.log(action) switch( action.type ){ diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index d0afb863..ee0c11a9 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -219,145 +219,6 @@ export function getTrack( uri ){ } } - -/** - * Get a single artist - * - * @param uri string - **/ -export function getArtist( uri ){ - return (dispatch, getState) => { - - // flush out the previous store value - dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: false }); - - var artist = {}; - - // get both the artist and the top tracks - $.when( - - sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) ) - .then( response => { - Object.assign(artist, response); - }), - - sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/top-tracks?country='+getState().spotify.country ) - .then( response => { - Object.assign(artist, response); - }), - - sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' ) - .then( response => { - Object.assign(artist, { related_artists: response.artists }); - }), - - sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' ) - .then( response => { - Object.assign(artist, { albums: response.items, albums_more: response.next }); - }) - - ).then( () => { - dispatch({ - type: 'SPOTIFY_ARTIST_LOADED', - data: artist - }); - }); - } -} - -export function getArtists( uris ){ - return (dispatch, getState) => { - - // flush out the previous store value - dispatch({ type: 'SPOTIFY_ARTISTS_LOADED', data: false }); - - // now get all the artists for this album (full objects) - var ids = ''; - for( var i = 0; i < uris.length; i++ ){ - if( ids != '' ) ids += ',' - ids += helpers.getFromUri( 'artistid', uris[i] ); - } - - sendRequest( dispatch, getState, 'artists/?ids='+ids ) - .then( response => { - dispatch({ - type: 'SPOTIFY_ARTISTS_LOADED', - data: response.artists - }); - }); - } -} - -/** - * Single album - * - * @oaram uri string - **/ -export function getAlbum( uri ){ - return (dispatch, getState) => { - - // flush out the previous store value - dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false }); - - sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) ) - .then( response => { - - var album = response - - // now get all the artists for this album (full objects) - // we do this to get the artist artwork - var artist_ids = []; - for( var i = 0; i < album.artists.length; i++ ){ - artist_ids.push( helpers.getFromUri( 'artistid', album.artists[i].uri ) ) - } - - sendRequest( dispatch, getState, 'artists/?ids='+artist_ids ) - .then( response => { - var artists = response.artists - - // finally dispatch the loaded action - dispatch({ - type: 'SPOTIFY_ALBUM_LOADED', - data: Object.assign({}, album, {artists: artists}) - }); - }); - - }); - } -} - - -export function getLibraryArtists(){ - return (dispatch, getState) => { - - dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false }); - - sendRequest( dispatch, getState, 'me/following?type=artist' ) - .then( response => { - dispatch({ - type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', - data: response.artists - }); - }); - } -} - - -export function getLibraryAlbums(){ - return (dispatch, getState) => { - - dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false }); - - sendRequest( dispatch, getState, 'me/albums' ) - .then( response => { - dispatch({ - type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', - data: response - }); - }); - } -} - export function getLibraryTracks(){ return (dispatch, getState) => { @@ -497,10 +358,217 @@ export function getSearchResults( query, type = 'album,artist,playlist,track', l } +/** + * =============================================================== ARTIST(S) ============ + * ====================================================================================== + **/ + +/** + * Get a single artist + * + * @param uri string + **/ +export function getArtist( uri ){ + return (dispatch, getState) => { + + // flush out the previous store value + dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: false }); + + var artist = {}; + + // get both the artist and the top tracks + $.when( + + sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) ) + .then( response => { + Object.assign(artist, response); + }), + + sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/top-tracks?country='+getState().spotify.country ) + .then( response => { + Object.assign(artist, response); + }), + + sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' ) + .then( response => { + Object.assign(artist, { related_artists: response.artists }); + }), + + sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' ) + .then( response => { + Object.assign(artist, { albums: response.items, albums_more: response.next }); + }), + + sendRequest( dispatch, getState, 'me/following/contains?type=artist&ids='+ helpers.getFromUri('artistid', uri) ) + .then( response => { + var is_following = 0 + if( response.length > 0 ) is_following = response[0] + Object.assign(artist, { following: response[0] } ); + }) + + ).then( () => { + dispatch({ + type: 'SPOTIFY_ARTIST_LOADED', + data: artist + }); + }); + } +} + +export function getArtists( uris ){ + return (dispatch, getState) => { + + // flush out the previous store value + dispatch({ type: 'SPOTIFY_ARTISTS_LOADED', data: false }); + + // now get all the artists for this album (full objects) + var ids = ''; + for( var i = 0; i < uris.length; i++ ){ + if( ids != '' ) ids += ',' + ids += helpers.getFromUri( 'artistid', uris[i] ); + } + + sendRequest( dispatch, getState, 'artists/?ids='+ids ) + .then( response => { + dispatch({ + type: 'SPOTIFY_ARTISTS_LOADED', + data: response.artists + }); + }); + } +} + + +export function getLibraryArtists(){ + return (dispatch, getState) => { + + dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false }); + + sendRequest( dispatch, getState, 'me/following?type=artist' ) + .then( response => { + dispatch({ + type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', + data: response.artists + }); + }); + } +} + +export function toggleArtistInLibrary( uri, method ){ + if( method == 'PUT' ) var new_state = 1 + if( method == 'DELETE' ) var new_state = 0 + + return (dispatch, getState) => { + sendRequest( dispatch, getState, 'me/following?type=artist&ids='+ helpers.getFromUri('artistid',uri), method, {} ) + .then( response => { + dispatch({ + type: 'SPOTIFY_ARTIST_FOLLOWING', + uri: uri, + data: new_state + }); + }); + } +} + /** - * Playlists + * =============================================================== ALBUM(S) ============= + * ====================================================================================== + **/ + +/** + * Single album + * + * @oaram uri string + **/ +export function getAlbum( uri ){ + return (dispatch, getState) => { + + // flush out the previous store value + dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false }); + + var album = {} + + $.when( + + // get the album + sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) ) + .then( response => { + + Object.assign(album, response) + + // now get all the artists for this album (full objects) + // we do this to get the artist artwork + var artist_ids = []; + for( var i = 0; i < album.artists.length; i++ ){ + artist_ids.push( helpers.getFromUri( 'artistid', album.artists[i].uri ) ) + } + + // get all album artists + sendRequest( dispatch, getState, 'artists/?ids='+artist_ids ) + .then( response => { + var artists = response.artists + Object.assign(album, {artists: artists}) + }); + + }), + + // TODO: Check if we're authenticated before sending this request, otherwise we get a 403 + sendRequest( dispatch, getState, 'me/albums/contains?ids='+ helpers.getFromUri('albumid', uri) ) + .then( response => { + var is_following = 0 + if( response.length > 0 ) is_following = response[0] + Object.assign(album, { following: response[0] } ); + }) + + ).then( () => { + dispatch({ + type: 'SPOTIFY_ALBUM_LOADED', + data: album + }); + }); + } +} + +export function getLibraryAlbums(){ + return (dispatch, getState) => { + + dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false }); + + sendRequest( dispatch, getState, 'me/albums' ) + .then( response => { + dispatch({ + type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', + data: response + }); + }); + } +} + +export function toggleAlbumInLibrary( uri, method ){ + if( method == 'PUT' ) var new_state = 1 + if( method == 'DELETE' ) var new_state = 0 + + return (dispatch, getState) => { + sendRequest( dispatch, getState, 'me/albums?ids='+ helpers.getFromUri('albumid',uri), method ) + .then( response => { + dispatch({ + type: 'SPOTIFY_ALBUM_FOLLOWING', + uri: uri, + data: new_state + }); + }); + } +} + + + + + +/** + * =============================================================== PLAYLIST(S) ========== + * ====================================================================================== **/ export function createPlaylist( name, is_public ){ @@ -609,6 +677,7 @@ export function toggleFollowingPlaylist( uri, method ){ .then( response => { dispatch({ type: 'SPOTIFY_PLAYLIST_FOLLOWING', + uri: uri, data: new_state }); }); diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index e6821bb4..7e743b98 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -134,6 +134,10 @@ export default function reducer(ui = {}, action){ }) return Object.assign({}, ui, { album: album }); + case 'SPOTIFY_ALBUM_FOLLOWING': + var album = Object.assign({}, ui.album, { following: action.data }) + return Object.assign({}, ui, { album: album }); + /** @@ -161,6 +165,10 @@ export default function reducer(ui = {}, action){ }) return Object.assign({}, ui, { artist: artist }); + case 'SPOTIFY_ARTIST_FOLLOWING': + var artist = Object.assign({}, ui.artist, { following: action.data }) + return Object.assign({}, ui, { artist: artist }); + /** * Playlists diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 3e49c278..6cd98b1c 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -64,24 +64,22 @@ class Album extends React.Component{ } follow(){ - this.props.spotifyActions.toggleFollowingAlbum( this.props.params.uri, 'PUT' ) + this.props.spotifyActions.toggleAlbumInLibrary( this.props.params.uri, 'PUT' ) } // TODO: Once unfollowing occurs, remove playlist from global playlists list unfollow(){ - this.props.spotifyActions.toggleFollowingAlbum( this.props.params.uri, 'DELETE' ) + this.props.spotifyActions.toggleAlbumInLibrary( this.props.params.uri, 'DELETE' ) } renderExtraButtons(){ switch( helpers.uriSource( this.props.params.uri ) ){ - case 'spotify': if( !this.props.spotify_authorized ) return null - if( this.props.playlist.following ){ - return + if( this.props.album.following ){ + return } - return - + return } } @@ -133,6 +131,7 @@ class Album extends React.Component{ const mapStateToProps = (state, ownProps) => { return { album: state.ui.album, + spotify_authorized: state.spotify.authorized, mopidy_connected: state.mopidy.connected }; } diff --git a/src/js/views/Artist.js b/src/js/views/Artist.js index f59c06bb..6a43a13e 100755 --- a/src/js/views/Artist.js +++ b/src/js/views/Artist.js @@ -51,6 +51,29 @@ class Artist extends React.Component{ this.props.spotifyActions.getURL( this.props.artist.albums_more, 'SPOTIFY_ARTIST_ALBUMS_LOADED_MORE' ); } + play(){ + alert('Yet to be implemented') + } + + follow(){ + this.props.spotifyActions.toggleArtistInLibrary( this.props.params.uri, 'PUT' ) + } + + unfollow(){ + this.props.spotifyActions.toggleArtistInLibrary( this.props.params.uri, 'DELETE' ) + } + + renderExtraButtons(){ + switch( helpers.uriSource( this.props.params.uri ) ){ + case 'spotify': + if( !this.props.spotify_authorized ) return null + if( this.props.artist.following ){ + return + } + return + } + } + render(){ if( !this.props.artist ) return null var scheme = helpers.uriSource( this.props.params.uri ); @@ -60,8 +83,16 @@ class Artist extends React.Component{
+ +

{ this.props.artist.name }

+ +
+ + { this.renderExtraButtons() } +
+
    { this.props.artist.followers ?
  • { this.props.artist.followers.total.toLocaleString() } followers
  • : null } { this.props.artist.popularity ?
  • { this.props.artist.popularity }% popularity
  • : null } @@ -69,6 +100,7 @@ class Artist extends React.Component{ { scheme == 'spotify' ?
  • Spotify artist
  • : null } { scheme == 'local' ?
  • Local artist
  • : null }
+
@@ -104,8 +136,9 @@ class Artist extends React.Component{ const mapStateToProps = (state, ownProps) => { return { - mopidy_connected: state.mopidy.connected, - artist: state.ui.artist + artist: state.ui.artist, + spotify_authorized: state.spotify.authorized, + mopidy_connected: state.mopidy.connected } } diff --git a/src/scss/views/_artist.scss b/src/scss/views/_artist.scss index 54597f69..018ce188 100755 --- a/src/scss/views/_artist.scss +++ b/src/scss/views/_artist.scss @@ -16,6 +16,11 @@ padding-top: 30px; padding-bottom: 45px; } + + .actions { + float: left; + margin-right: 20px; + } } .artist-list {