diff --git a/src/js/bootstrap.js b/src/js/bootstrap.js index 5901fe30..e0693d88 100755 --- a/src/js/bootstrap.js +++ b/src/js/bootstrap.js @@ -24,20 +24,21 @@ var initialState = { }, spotify: { country: 'NZ', - locale: 'en_NZ' + locale: 'en_NZ', + me: false } }; // if we've got a stored version of mopidy state, load and merge if( localStorage.getItem('mopidy') ){ var storedMopidy = JSON.parse( localStorage.getItem('mopidy') ); - Object.assign(initialState, { mopidy: storedMopidy } ); + initialState.mopidy = Object.assign(initialState.mopidy, storedMopidy ); } // if we've got a stored version of spotify state, load and merge if( localStorage.getItem('spotify') ){ var storedSpotify = JSON.parse( localStorage.getItem('spotify') ); - Object.assign(initialState, { spotify: storedSpotify } ); + initialState.spotify = Object.assign(initialState.spotify, storedSpotify ); } let store = createStore( diff --git a/src/js/components/SpotifyAuthenticationFrame.js b/src/js/components/SpotifyAuthenticationFrame.js index 28557396..ce6a45b4 100755 --- a/src/js/components/SpotifyAuthenticationFrame.js +++ b/src/js/components/SpotifyAuthenticationFrame.js @@ -24,11 +24,22 @@ class SpotifyAuthenticationFrame extends React.Component{ if( !/^https?:\/\/jamesbarnsley\.co\.nz/.test(event.origin) ) return false; var data = JSON.parse(event.data); - self.props.actions.completeAuthorization( data ); + self.props.actions.authorizationGranted( data ); }, false); } + renderMe(){ + if( this.props.spotify.me ){ + if( this.props.spotify.me.display_name ){ + return Logged in as { this.props.spotify.me.display_name } + }else{ + return Logged in as { this.props.spotify.me.id } + } + } + return null; + } + renderAuthorizeButton(){ if( this.props.spotify.authorizing ){ return ( @@ -39,7 +50,10 @@ class SpotifyAuthenticationFrame extends React.Component{ ); }else if( this.props.spotify.authorized ){ return ( - +
+ + { this.renderMe() } +
); }else{ return ( diff --git a/src/js/components/TrackList.js b/src/js/components/TrackList.js index 621cfc88..42412825 100755 --- a/src/js/components/TrackList.js +++ b/src/js/components/TrackList.js @@ -49,24 +49,24 @@ class TrackList extends React.Component{ this.setState({ tracks: tracks, lastSelectedTrack: index }); } - handleDoubleClick( e, index ){ - var tracks = this.state.tracks; - this.props.actions.changeTrack( tracks[index].tlid ) - } - - deleteSelected(){ - + selectedTracks(){ function isSelected( track ){ return ( typeof(track.selected) !== 'undefined' && track.selected ); } + return this.state.tracks.filter(isSelected) + } - var selectedTracks = this.state.tracks.filter(isSelected) - var selectedTracksTlids = []; - for( var i = 0; i < selectedTracks.length; i++ ){ - selectedTracksTlids.push( selectedTracks[i].tlid ) - } + handleDoubleClick( e, index ){ + var tracks = this.state.tracks; + this.props.playTrack( tracks[index] ) + } - this.props.actions.removeTracks( selectedTracksTlids ) + playTracks(){ + this.props.playTracks( this.selectedTracks() ) + } + + removeTracks(){ + this.props.removeTracks( this.selectedTracks() ) } componentWillReceiveProps( nextProps ){ @@ -100,7 +100,8 @@ class TrackList extends React.Component{ ) } - + + ); } diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 87060bb7..0b82f463 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -5,6 +5,8 @@ const localstorageMiddleware = (function(){ * The actual middleware inteceptor **/ return store => next => action => { + + console.log(action) // proceed as normal first // this way, any reducers and middleware do their thing BEFORE we store our new state @@ -28,12 +30,18 @@ const localstorageMiddleware = (function(){ localStorage.setItem('spotify', JSON.stringify(spotify)); break; - case 'SPOTIFY_COMPLETE_AUTHORIZATION': - var spotify = { - authorized: true, - access_token: action.data.access_token, - refresh_token: action.data.refresh_token - }; + case 'SPOTIFY_AUTHORIZATION_COMPLETE': + var spotify = JSON.parse( localStorage.getItem('spotify') ); + if( !spotify ) spotify = {}; + console.log(spotify) + Object.assign( + spotify,{ + authorized: true, + access_token: action.data.access_token, + refresh_token: action.data.refresh_token, + me: action.data.me + } + ); localStorage.setItem('spotify', JSON.stringify(spotify)); break; } diff --git a/src/js/services/mopidy/actions.js b/src/js/services/mopidy/actions.js index e760311d..dccf9649 100755 --- a/src/js/services/mopidy/actions.js +++ b/src/js/services/mopidy/actions.js @@ -30,6 +30,14 @@ export function changeTrack( tlid ){ } } +export function playTracks( uris ){ + return { + type: 'MOPIDY_PLAY_TRACKS', + call: 'tracklist.add', + value: { at_position: 0, uris: uris } + } +} + export function removeTracks( tlids ){ return { type: 'MOPIDY_REMOVE_TRACKS', diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 2b02185b..6987ea87 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -128,6 +128,13 @@ const MopidyMiddleware = (function(){ instruct( socket, store, action.call, action.value ) break; + case 'MOPIDY_PLAY_TRACKS': + var callback = function(){ + store.dispatch({ type: 'MOPIDY_TEST', model: 'yeah', data: {} }) + } + instruct( socket, store, action.call, action.value, callback ) + break; + // This action is irrelevant to us, pass it on to the next middleware default: return next(action); diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 4554c439..286ce1fd 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -22,9 +22,9 @@ export function removeAuthorization(){ } } -export function completeAuthorization( data ){ +export function authorizationGranted( data ){ return { - type: 'SPOTIFY_COMPLETE_AUTHORIZATION', + type: 'SPOTIFY_AUTHORIZATION_GRANTED', data: data } } diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index 63dd7e49..a3369a87 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -38,6 +38,15 @@ const SpotifyMiddleware = (function(){ switch(action.type){ + case 'SPOTIFY_AUTHORIZATION_GRANTED': + sendRequest( action.data.access_token, 'me' ) + .then( (response) => { + var data = action.data; + data.me = response; + store.dispatch({ type: 'SPOTIFY_AUTHORIZATION_COMPLETE', data: data }) + }); + break; + case 'SPOTIFY_LOAD_ALBUM': store.dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false }) diff --git a/src/js/services/spotify/reducer.js b/src/js/services/spotify/reducer.js index 6a1c6bd0..73e6bd6d 100755 --- a/src/js/services/spotify/reducer.js +++ b/src/js/services/spotify/reducer.js @@ -8,11 +8,12 @@ export default function reducer(spotify = {}, action){ case 'SPOTIFY_START_AUTHORIZATION': return Object.assign({}, spotify, { authorizing: true }); - case 'SPOTIFY_COMPLETE_AUTHORIZATION': + case 'SPOTIFY_AUTHORIZATION_COMPLETE': return Object.assign({}, spotify, { authorizing: false, authorized: true, - authorization: action.data, + authorization: action.data, + me: action.data.me, token: action.data.access_token }); @@ -20,7 +21,9 @@ export default function reducer(spotify = {}, action){ return Object.assign({}, spotify, { authorizing: false, authorization: false, - authorized: false + authorized: false, + token: false, + me: false }); case 'SPOTIFY_CONNECTED': diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 3e6a4b72..4c89591f 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -5,6 +5,7 @@ import { bindActionCreators } from 'redux' import TrackList from '../components/TrackList' import * as spotifyActions from '../services/spotify/actions' +import * as mopidyActions from '../services/mopidy/actions' class Album extends React.Component{ @@ -24,12 +25,30 @@ class Album extends React.Component{ } } + playTracks( tracks ){ + var uris = []; + for( var i = 0; i < tracks.length; i++ ){ + uris.push( tracks[i].uri ) + } + this.props.mopidyActions.playTracks( uris ) + } + + playTrack( track ){ + var uris = [track.uri]; + this.props.mopidyActions.playTracks( uris ) + } + render(){ if( this.props.spotify.album ){ return (

{ this.props.spotify.album.name }

- + this.playTracks( tracks ) } + playTrack={ track => this.playTrack( track ) } + />
); } @@ -50,6 +69,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = (dispatch) => { return { + mopidyActions: bindActionCreators(mopidyActions, dispatch), spotifyActions: bindActionCreators(spotifyActions, dispatch) } } diff --git a/src/js/views/Queue.js b/src/js/views/Queue.js index 35e496dc..52ab375e 100755 --- a/src/js/views/Queue.js +++ b/src/js/views/Queue.js @@ -33,12 +33,29 @@ class Queue extends React.Component{ renderTrackList(){ if( this.props.mopidy && this.props.mopidy.tracks ){ return ( - + this.removeTracks( tracks ) } + playTracks={ null } + playTrack={ track => this.playTrack( track ) } + /> ); } return null; } + removeTracks( tracks ){ + var tlids = []; + for( var i = 0; i < tracks.length; i++ ){ + tlids.push( tracks[i].tlid ) + } + this.props.actions.removeTracks( tlids ) + } + + playTrack( track ){ + this.props.actions.changeTrack( track.tlid ) + } + render(){ return (