diff --git a/src/js/components/FollowButton.js b/src/js/components/FollowButton.js new file mode 100755 index 00000000..c0d0fb16 --- /dev/null +++ b/src/js/components/FollowButton.js @@ -0,0 +1,56 @@ + +import React, { PropTypes } from 'react' +import { connect } from 'react-redux' +import { Link } from 'react-router' +import { createStore, bindActionCreators } from 'redux' +import FontAwesome from 'react-fontawesome' + +import * as helpers from '../helpers' +import * as spotifyActions from '../services/spotify/actions' + +class FollowButton extends React.Component{ + + constructor(props) { + super(props); + } + + componentDidMount(){ + this.props.spotifyActions.following(this.props.uri) + } + + remove(){ + this.props.spotifyActions.following(this.props.uri, 'DELETE') + } + + add(){ + this.props.spotifyActions.following(this.props.uri, 'PUT') + } + + render(){ + if( !this.props.spotify_authorized || !this.props.uri ) return false + var item = this.props[helpers.uriType( this.props.uri )] + + if( item.following === true ){ + return + }else{ + return + } + } +} + +const mapStateToProps = (state, ownProps) => { + return { + spotify_authorized: state.spotify.authorized, + artist: state.ui.artist, + album: state.ui.album, + playlist: state.ui.playlist + } +} + +const mapDispatchToProps = (dispatch) => { + return { + spotifyActions: bindActionCreators(spotifyActions, dispatch) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(FollowButton) \ No newline at end of file diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 868ef3b1..3ac79d43 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -15,6 +15,7 @@ const localstorageMiddleware = (function(){ var actions_to_log = null //actions_to_log = 'SPOTIFY' //actions_to_log = 'MOPIDY' + actions_to_log = 'ALBUM_' 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 ee0c11a9..022fe6b6 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -357,6 +357,53 @@ export function getSearchResults( query, type = 'album,artist,playlist,track', l } } +export function following(uri, method = 'GET'){ + return (dispatch, getState) => { + + dispatch({ type: 'FOLLOWING_LOADING' }); + + if( method == 'PUT' ) var is_following = true + if( method == 'DELETE' ) var is_following = false + + var asset_name = helpers.uriType(uri); + var endpoint, data + switch( asset_name ){ + case 'album': + if( method == 'GET'){ + endpoint = 'me/albums/contains/?ids='+ helpers.getFromUri('albumid', uri) + }else{ + endpoint = 'me/albums/?ids='+ helpers.getFromUri('albumid', uri) + } + break + case 'artist': + if( method == 'GET' ){ + endpoint = 'me/following/contains?type=artist&ids='+ helpers.getFromUri('artistid', uri) + }else{ + endpoint = 'me/following?type=artist&ids='+ helpers.getFromUri('artistid', uri) + data = {} + } + break + case 'playlist': + if( method == 'GET' ){ + endpoint = 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'/followers/contains?ids='+ getState().spotify.me.id + }else{ + endpoint = 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'/followers' + } + break + } + + sendRequest( dispatch, getState, endpoint, method, data ) + .then( response => { + if( response ) is_following = response + if( typeof(is_following) === 'object' ) is_following = is_following[0] + dispatch({ + type: asset_name.toUpperCase()+'_FOLLOWING_LOADED', + is_following: is_following + }); + }); + } +} + /** * =============================================================== ARTIST(S) ============ @@ -397,13 +444,6 @@ export function getArtist( uri ){ 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( () => { @@ -454,22 +494,6 @@ export function getLibraryArtists(){ } } -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 - }); - }); - } -} - /** @@ -488,46 +512,30 @@ export function getAlbum( uri ){ // flush out the previous store value dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false }); - var album = {} + // get the album + sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) ) + .then( response => { - $.when( + var album = response - // get the album - sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) ) - .then( 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 ) ) + } - 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}) + // get all album artists + sendRequest( dispatch, getState, 'artists/?ids='+artist_ids ) + .then( response => { + Object.assign(album, { artists: response.artists }) + dispatch({ + type: 'SPOTIFY_ALBUM_LOADED', + data: album }); + }); - }), - - // 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 - }); - }); + }) } } @@ -603,30 +611,14 @@ export function getPlaylist( uri ){ // flush out the previous store value dispatch({ type: 'SPOTIFY_PLAYLIST_LOADED', data: false }); - var playlist = {}; - - $.when( - - // get the main playlist object - sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'?market='+getState().spotify.country ) - .then( response => { - Object.assign( playlist, response ); - }), - - // TODO: Check if we're authenticated before sending this request, otherwise we get a 403 - sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) + '/playlists/'+ helpers.getFromUri('playlistid',uri) + '/followers/contains?ids='+getState().spotify.me.id ) - .then( response => { - var is_following = 0 - if( response.length > 0 ) is_following = response[0] - Object.assign(playlist, { following: response[0] } ); - }) - - ).then( () => { + // get the main playlist object + sendRequest( dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'?market='+getState().spotify.country ) + .then( response => { dispatch({ type: 'SPOTIFY_PLAYLIST_LOADED', - data: playlist - }); - }); + data: response + }) + }) } } diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index 7e743b98..406b839a 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -101,6 +101,10 @@ export default function reducer(ui = {}, action){ current_track: current_track }); + case 'FOLLOWING_LOADING': + return Object.assign({}, ui, { following_loading: true }) + + /** @@ -134,9 +138,9 @@ 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 }); + case 'ALBUM_FOLLOWING_LOADED': + var album = Object.assign({}, ui.album, { following: action.is_following }) + return Object.assign({}, ui, { album: album, following_loading: false }); @@ -165,9 +169,9 @@ 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 }); + case 'ARTIST_FOLLOWING_LOADED': + var artist = Object.assign({}, ui.artist, { following: action.is_following }) + return Object.assign({}, ui, { artist: artist, following_loading: false }); /** @@ -223,10 +227,6 @@ export default function reducer(ui = {}, action){ }) return Object.assign({}, ui, { playlist: playlist }); - case 'SPOTIFY_PLAYLIST_FOLLOWING': - var playlist = Object.assign({}, ui.playlist, { following: action.data }) - return Object.assign({}, ui, { playlist: playlist }); - case 'PLAYLIST_TRACKS_REMOVED': var tracks = Object.assign([], ui.playlist.tracks) var indexes = action.tracks_indexes.reverse() @@ -262,6 +262,10 @@ export default function reducer(ui = {}, action){ var playlist = Object.assign({}, ui.playlist, { snapshot_id: snapshot_id, tracks: tracks }) return Object.assign({}, ui, { playlist: playlist }); + case 'PLAYLIST_FOLLOWING_LOADED': + var playlist = Object.assign({}, ui.playlist, { following: action.is_following }) + return Object.assign({}, ui, { playlist: playlist, following_loading: false }); + /** * Library Playlists **/ diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 6cd98b1c..9d6ee0da 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -10,6 +10,7 @@ import Thumbnail from '../components/Thumbnail' import Parallax from '../components/Parallax' import ArtistSentence from '../components/ArtistSentence' import ArtistGrid from '../components/ArtistGrid' +import FollowButton from '../components/FollowButton' import Dater from '../components/Dater' import LazyLoadListener from '../components/LazyLoadListener' @@ -63,26 +64,6 @@ class Album extends React.Component{ this.props.mopidyActions.playURIs( tracks_uris ) } - follow(){ - this.props.spotifyActions.toggleAlbumInLibrary( this.props.params.uri, 'PUT' ) - } - - // TODO: Once unfollowing occurs, remove playlist from global playlists list - unfollow(){ - 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.album.following ){ - return - } - return - } - } - render(){ if( !this.props.album ) return null @@ -94,7 +75,7 @@ class Album extends React.Component{