diff --git a/src/js/components/AlbumGridItem.js b/src/js/components/AlbumGridItem.js
index 2118227c..4e15f9c9 100755
--- a/src/js/components/AlbumGridItem.js
+++ b/src/js/components/AlbumGridItem.js
@@ -10,10 +10,15 @@ export default class AlbumGridItem extends React.Component{
}
render(){
- var link = '/album/' + this.props.item.uri;
+ var item = this.props.item;
+ if( typeof(item.album) !== 'undefined' ){
+ item.album.added_at = item.added_at;
+ item = item.album;
+ }
+ var link = '/album/' + item.uri;
return (
-
+ { item.images ? : item.name }
);
}
diff --git a/src/js/components/Player.js b/src/js/components/Player.js
index 029a3ffc..3a190619 100755
--- a/src/js/components/Player.js
+++ b/src/js/components/Player.js
@@ -13,11 +13,22 @@ class Player extends React.Component{
super(props);
}
+ renderTrackInFocus(){
+ if( this.props.mopidy && this.props.mopidy.trackInFocus ){
+ return (
+
+ { this.renderTrackInFocus() }
{ playButton }
-
this.props.actions.instruct('playback.previous')}>
+ this.props.actions.previous()}>
-
this.props.actions.instruct('playback.next')}>
+ this.props.actions.next()}>
{ consumeButton }
diff --git a/src/js/components/TrackList.js b/src/js/components/TrackList.js
index 42412825..0d111c6f 100755
--- a/src/js/components/TrackList.js
+++ b/src/js/components/TrackList.js
@@ -2,7 +2,7 @@
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
-import * as actions from '../services/mopidy/actions'
+import * as mopidyActions from '../services/mopidy/actions'
import Track from './Track'
@@ -17,6 +17,10 @@ class TrackList extends React.Component{
}
}
+ componentWillReceiveProps( nextProps ){
+ this.setState({ tracks: nextProps.tracks });
+ }
+
handleClick( e, index ){
var tracks = this.state.tracks;
@@ -49,6 +53,11 @@ class TrackList extends React.Component{
this.setState({ tracks: tracks, lastSelectedTrack: index });
}
+ handleDoubleClick( e, index ){
+ var tracks = this.state.tracks;
+ this.playTrack( tracks[index] )
+ }
+
selectedTracks(){
function isSelected( track ){
return ( typeof(track.selected) !== 'undefined' && track.selected );
@@ -56,21 +65,38 @@ class TrackList extends React.Component{
return this.state.tracks.filter(isSelected)
}
- handleDoubleClick( e, index ){
- var tracks = this.state.tracks;
- this.props.playTrack( tracks[index] )
+ playTracks(){
+
+ var tracks = this.selectedTracks();
+
+ if( typeof(this.props.playTracks) !== 'undefined' ){
+ return this.props.playTracks( tracks );
+ }
+
+ var uris = [];
+ for( var i = 0; i < tracks.length; i++ ){
+ uris.push( tracks[i].uri )
+ }
+ return this.props.mopidyActions.playTracks( uris )
}
- playTracks(){
- this.props.playTracks( this.selectedTracks() )
+ playTrack( track ){
+
+ if( typeof(this.props.playTrack) !== 'undefined' ){
+ return this.props.playTrack( this.selectedTracks() );
+ }
+
+ var uris = [track.uri];
+ this.props.mopidyActions.playTracks( uris )
}
removeTracks(){
- this.props.removeTracks( this.selectedTracks() )
- }
- componentWillReceiveProps( nextProps ){
- this.setState({ tracks: nextProps.tracks });
+ var tracks = this.selectedTracks();
+
+ if( typeof(this.props.removeTracks) !== 'undefined' ){
+ return this.props.removeTracks( tracks );
+ }
}
render(){
@@ -122,7 +148,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => {
return {
- actions: bindActionCreators(actions, dispatch)
+ mopidyActions: bindActionCreators(mopidyActions, dispatch)
}
}
diff --git a/src/js/index.js b/src/js/index.js
index b70a9552..a0441b1d 100755
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -18,6 +18,8 @@ import Artist from './views/Artist'
import Queue from './views/Queue'
import Settings from './views/Settings'
import LibraryArtists from './views/LibraryArtists'
+import LibraryAlbums from './views/LibraryAlbums'
+import LibraryTracks from './views/LibraryTracks'
ReactDOM.render(
@@ -25,6 +27,8 @@ ReactDOM.render(
+
+
diff --git a/src/js/services/mopidy/actions.js b/src/js/services/mopidy/actions.js
index dccf9649..3f6fc59f 100755
--- a/src/js/services/mopidy/actions.js
+++ b/src/js/services/mopidy/actions.js
@@ -33,8 +33,18 @@ export function changeTrack( tlid ){
export function playTracks( uris ){
return {
type: 'MOPIDY_PLAY_TRACKS',
+ uris: uris
+ }
+}
+
+export function enqueueTracks( uris, at_position = false ){
+ if( typeof(uris) !== 'array' ) uris = [uris];
+ var value = { uris: uris };
+ if( at_position ) value.at_position = at_position;
+ return {
+ type: 'MOPIDY_ENQUEUE_TRACKS',
call: 'tracklist.add',
- value: { at_position: 0, uris: uris }
+ value: value
}
}
@@ -54,3 +64,18 @@ export function instruct( call, value ){
}
}
+export function play(){
+ return instruct('playback.play');
+}
+
+export function pause(){
+ return instruct('playback.pause');
+}
+
+export function next(){
+ return instruct('playback.next');
+}
+
+export function previous(){
+ return instruct('playback.previous');
+}
diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js
index 6987ea87..3623f954 100755
--- a/src/js/services/mopidy/middleware.js
+++ b/src/js/services/mopidy/middleware.js
@@ -1,6 +1,6 @@
import Mopidy from 'mopidy'
-import actions from './actions'
+var actions = require('./actions.js')
const MopidyMiddleware = (function(){
@@ -38,7 +38,7 @@ const MopidyMiddleware = (function(){
break;
case 'event:volumeChanged':
- store.dispatch({ type: 'MOPIDY_Volume', data: data.volume });
+ store.dispatch({ type: 'MOPIDY_VOLUME', data: data.volume });
break;
case 'event:optionsChanged':
@@ -61,8 +61,9 @@ const MopidyMiddleware = (function(){
* @param string model = which Mopidy model (playback, tracklist, etc)
* @param string property = TlTracks, Consume, etc
* @param string value (optional) = value of the property to pass
+ * @return promise
**/
- const instruct = ( ws, store, call, value = false ) => {
+ const instruct = ( ws, store, call, value = {} ) => {
var callParts = call.split('.');
var model = callParts[0];
@@ -71,22 +72,19 @@ const MopidyMiddleware = (function(){
property = property.replace('get','');
property = property.replace('set','');
- // if we have a value, we need to include in our payload
- if( value ){
+ return new Promise( (resolve, reject) => {
ws[model][method]( value )
.then(
- response => store.dispatch({ type: 'MOPIDY_'+property, model: model, data: response }),
- error => console.error( error )
+ response => {
+ store.dispatch({ type: 'MOPIDY_'+property.toUpperCase(), model: model, data: response });
+ resolve(response);
+ },
+ error => {
+ console.error(error)
+ reject(error);
+ }
);
-
- // no value, so omit the payload
- }else{
- ws[model][method]()
- .then(
- response => store.dispatch({ type: 'MOPIDY_'+property, model: model, data: response }),
- error => console.error( error )
- );
- }
+ });
}
/**
@@ -97,6 +95,7 @@ const MopidyMiddleware = (function(){
* it just proceeds to the next middleware, or default functionality
**/
return store => next => action => {
+
switch(action.type) {
case 'MOPIDY_CONNECT':
@@ -129,10 +128,20 @@ const MopidyMiddleware = (function(){
break;
case 'MOPIDY_PLAY_TRACKS':
- var callback = function(){
- store.dispatch({ type: 'MOPIDY_TEST', model: 'yeah', data: {} })
- }
- instruct( socket, store, action.call, action.value, callback )
+
+ // add our first track
+ instruct( socket, store, 'tracklist.add', { uri: action.uris[0], at_position: 0 } )
+ .then( response => {
+
+ // play it
+ store.dispatch( actions.changeTrack( response[0].tlid ) );
+
+ // add the rest of our uris (if any)
+ action.uris.shift();
+ if( action.uris.length > 0 ){
+ store.dispatch( actions.enqueueTracks( action.uris, 1 ) )
+ }
+ })
break;
// This action is irrelevant to us, pass it on to the next middleware
diff --git a/src/js/services/mopidy/reducer.js b/src/js/services/mopidy/reducer.js
index dafd0280..78f39c81 100755
--- a/src/js/services/mopidy/reducer.js
+++ b/src/js/services/mopidy/reducer.js
@@ -2,9 +2,6 @@
export default function reducer(mopidy = {}, action){
switch (action.type) {
- case 'MOPIDY_CONNECTING':
- return Object.assign({}, mopidy, { connected: false, connecting: true });
-
case 'MOPIDY_CONNECTED':
return Object.assign({}, mopidy, { connected: true, connecting: false });
@@ -25,37 +22,37 @@ export default function reducer(mopidy = {}, action){
/**
* Websocket-initiated actions
**/
- case 'MOPIDY_State':
+ case 'MOPIDY_STATE':
return Object.assign({}, mopidy, {
state: action.data
});
- case 'MOPIDY_Consume':
+ case 'MOPIDY_CONSUME':
return Object.assign({}, mopidy, {
consume: action.data
});
- case 'MOPIDY_Random':
+ case 'MOPIDY_RANDOM':
return Object.assign({}, mopidy, {
random: action.data
});
- case 'MOPIDY_Repeat':
+ case 'MOPIDY_REPEAT':
return Object.assign({}, mopidy, {
repeat: action.data
});
- case 'MOPIDY_TlTracks':
+ case 'MOPIDY_TLTRACKS':
return Object.assign({}, mopidy, {
tracks: action.data
});
- case 'MOPIDY_CurrentTlTrack':
+ case 'MOPIDY_CURRENTTLTRACK':
return Object.assign({}, mopidy, {
trackInFocus: action.data
});
- case 'MOPIDY_Volume':
+ case 'MOPIDY_VOLUME':
return Object.assign({}, mopidy, {
volume: action.data
});
diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js
index 286ce1fd..ef3dc6f4 100755
--- a/src/js/services/spotify/actions.js
+++ b/src/js/services/spotify/actions.js
@@ -10,25 +10,6 @@ export function setConfig( config ){
}
}
-export function startAuthorization(){
- return {
- type: 'SPOTIFY_START_AUTHORIZATION'
- }
-}
-
-export function removeAuthorization(){
- return {
- type: 'SPOTIFY_REMOVE_AUTHORIZATION'
- }
-}
-
-export function authorizationGranted( data ){
- return {
- type: 'SPOTIFY_AUTHORIZATION_GRANTED',
- data: data
- }
-}
-
export function connect(){
return {
type: 'SPOTIFY_CONNECTING'
@@ -48,16 +29,176 @@ export function loadAlbum( uri ){
}
}
-export function loadArtist( uri ){
- return {
- type: 'SPOTIFY_LOAD_ARTIST',
- uri: uri
+
+
+/**
+ * Send an ajax request to the Spotify API
+ *
+ * @param endpoint string = the url to query (ie /albums/:uri)
+ * @param method string
+ * @param data mixed = request payload
+ * @return ajax promise
+ **/
+const sendRequest = (token, endpoint, method = 'GET', data = false) => {
+
+ var options = {
+ method: method,
+ cache: true,
+ url: 'https://api.spotify.com/v1/'+endpoint,
+ data: data
+ };
+
+ if( token ){
+ options.headers = {
+ Authorization: 'Bearer '+ token
+ }
+ }
+
+ return $.ajax( options );
+}
+
+
+/**
+ * Handle authorization process
+ **/
+
+export function startAuthorization(){
+ return { type: 'SPOTIFY_START_AUTHORIZATION' }
+}
+
+export function authorizationGranted( data ){
+ return { type: 'SPOTIFY_AUTHORIZATION_GRANTED', data: data }
+}
+
+export function removeAuthorization(){
+ return { type: 'SPOTIFY_REMOVE_AUTHORIZATION' }
+}
+
+
+/**
+ * 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 id = uri.replace('spotify:artist:','');
+ var artist = {};
+
+ // while we're fiddling about, go get the albums
+ dispatch(getArtistAlbums(uri));
+
+ // get both the artist and the top tracks
+ $.when(
+
+ sendRequest( false, 'artists/'+id )
+ .then( response => {
+ Object.assign(artist, response);
+ }),
+
+ sendRequest( false, 'artists/'+id+'/top-tracks?country='+getState().spotify.country )
+ .then( response => {
+ Object.assign(artist, response);
+ })
+
+ ).then( () => {
+ dispatch({
+ type: 'SPOTIFY_ARTIST_LOADED',
+ data: artist
+ });
+ });
}
}
-export function loadLibraryArtists(){
- return {
- type: 'SPOTIFY_LOAD_LIBRARY_ARTISTS'
+export function getArtistAlbums( uri ){
+ return dispatch => {
+ sendRequest( false, 'artists/'+ uri.replace('spotify:artist:','') +'/albums' )
+ .then( response => {
+ dispatch({
+ type: 'SPOTIFY_ARTIST_ALBUMS_LOADED',
+ data: response
+ });
+ });
}
}
+/**
+ * Single album
+ *
+ * @oaram uri string
+ **/
+export function getAlbum( uri ){
+ return dispatch => {
+
+ // flush out the previous store value
+ dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false });
+
+ sendRequest( false, 'albums/'+ uri.replace('spotify:album:','') )
+ .then( response => {
+
+ // inject the parent album object into each track for consistent track objects
+ for( var i = 0; i < response.tracks.items.length; i++ ){
+ response.tracks.items[i].album = {
+ name: response.name,
+ uri: response.uri
+ }
+ }
+
+ dispatch({
+ type: 'SPOTIFY_ALBUM_LOADED',
+ data: response
+ });
+ });
+ }
+}
+
+
+export function getLibraryArtists(){
+ return (dispatch, getState) => {
+
+ dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false });
+
+ sendRequest( getState().spotify.access_token, 'me/following?type=artist' )
+ .then( response => {
+ dispatch({
+ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED',
+ data: response
+ });
+ });
+ }
+}
+
+
+export function getLibraryAlbums(){
+ return (dispatch, getState) => {
+
+ dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false });
+
+ sendRequest( getState().spotify.access_token, 'me/albums' )
+ .then( response => {
+ dispatch({
+ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED',
+ data: response
+ });
+ });
+ }
+}
+
+export function getLibraryTracks(){
+ return (dispatch, getState) => {
+
+ dispatch({ type: 'SPOTIFY_LIBRARY_TRACKS_LOADED', data: false });
+
+ sendRequest( getState().spotify.access_token, 'me/tracks' )
+ .then( response => {
+ dispatch({
+ type: 'SPOTIFY_LIBRARY_TRACKS_LOADED',
+ data: response
+ });
+ });
+ }
+}
diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js
index a3369a87..3559f597 100755
--- a/src/js/services/spotify/middleware.js
+++ b/src/js/services/spotify/middleware.js
@@ -47,67 +47,6 @@ const SpotifyMiddleware = (function(){
});
break;
- case 'SPOTIFY_LOAD_ALBUM':
-
- store.dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false })
- var id = action.uri.replace('spotify:album:','');
-
- sendRequest( false, 'albums/'+id )
- .then( (response) => {
- for( var i = 0; i < response.tracks.items.length; i++ ){
- response.tracks.items[i].album = {
- name: response.name,
- uri: response.uri
- }
- }
- store.dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: response })
- });
- break;
-
-
- case 'SPOTIFY_LOAD_ARTIST':
-
- store.dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: false })
- store.dispatch({ type: 'SPOTIFY_ARTIST_ALBUMS_LOADED', data: false })
-
- var id = action.uri.replace('spotify:artist:','');
-
- sendRequest( false, 'artists/'+id )
- .then( (response) => {
- store.dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: response })
- });
-
- sendRequest( false, 'artists/'+id+'/albums' )
- .then( (response) => {
- store.dispatch({ type: 'SPOTIFY_ARTIST_ALBUMS_LOADED', data: response })
- });
-
- sendRequest( false, 'artists/'+id+'/top-tracks?country='+state.spotify.country )
- .then( (response) => {
- store.dispatch({ type: 'SPOTIFY_ARTIST_TRACKS_LOADED', data: response })
- });
- break;
-
-
- case 'SPOTIFY_LOAD_LIBRARY_ARTISTS':
-
- store.dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false })
-
- sendRequest( state.spotify.access_token, 'me/following?type=artist' )
- .then( (response) => {
- store.dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: response })
- });
- break;
-
-
- case 'SPOTIFY_CONNECT':
- console.log('Spotify wants to connect')
- break;
-
- case 'SPOTIFY_DISCONNECT':
- console.log('Spotify wants to DISconnect')
- 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/reducer.js b/src/js/services/spotify/reducer.js
index 73e6bd6d..21034d98 100755
--- a/src/js/services/spotify/reducer.js
+++ b/src/js/services/spotify/reducer.js
@@ -41,12 +41,12 @@ export default function reducer(spotify = {}, action){
case 'SPOTIFY_ARTIST_ALBUMS_LOADED':
return Object.assign({}, spotify, { artist_albums: action.data });
- case 'SPOTIFY_ARTIST_TRACKS_LOADED':
- return Object.assign({}, spotify, { artist_top_tracks: action.data });
-
case 'SPOTIFY_LIBRARY_ARTISTS_LOADED':
return Object.assign({}, spotify, { libraryArtists: action.data });
+ case 'SPOTIFY_LIBRARY_ALBUMS_LOADED':
+ return Object.assign({}, spotify, { libraryAlbums: action.data });
+
default:
return spotify
}
diff --git a/src/js/views/Album.js b/src/js/views/Album.js
index 4c89591f..137b2792 100755
--- a/src/js/views/Album.js
+++ b/src/js/views/Album.js
@@ -15,40 +15,22 @@ class Album extends React.Component{
// on render
componentDidMount(){
- this.props.spotifyActions.loadAlbum( this.props.params.uri );
+ this.props.spotifyActions.getAlbum( this.props.params.uri );
}
// when props changed
componentWillReceiveProps( nextProps ){
if( nextProps.params.uri != this.props.params.uri ){
- this.props.spotifyActions.loadAlbum( nextProps.params.uri );
+ this.props.spotifyActions.getAlbum( nextProps.params.uri );
}
}
- 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 ) }
- />
+
);
}
diff --git a/src/js/views/App.js b/src/js/views/App.js
index 2d88a544..c7ea001f 100755
--- a/src/js/views/App.js
+++ b/src/js/views/App.js
@@ -31,6 +31,8 @@ class App extends React.Component{
- Now playing
- Library: My artists
+ - Library: My albums
+ - Library: My playlists
- Settings
{this.props.children}
diff --git a/src/js/views/Artist.js b/src/js/views/Artist.js
index a58b2d7a..59180eb3 100755
--- a/src/js/views/Artist.js
+++ b/src/js/views/Artist.js
@@ -16,13 +16,13 @@ class Artist extends React.Component{
// on render
componentDidMount(){
- this.props.spotifyActions.loadArtist( this.props.params.uri );
+ this.props.spotifyActions.getArtist( this.props.params.uri );
}
// when props changed
componentWillReceiveProps( nextProps ){
if( nextProps.params.uri != this.props.params.uri ){
- this.props.spotifyActions.loadArtist( nextProps.params.uri );
+ this.props.spotifyActions.getArtist( nextProps.params.uri );
}
}
@@ -32,7 +32,7 @@ class Artist extends React.Component{
{ this.props.spotify.artist.name }
{ this.props.spotify.artist.followers.total.toLocaleString() } followers
- { this.props.spotify.artist_top_tracks ?
: null }
+ { this.props.spotify.artist.tracks ?
: null }
{ this.props.spotify.artist_albums ?
: null }
);
diff --git a/src/js/views/LibraryAlbums.js b/src/js/views/LibraryAlbums.js
new file mode 100755
index 00000000..714f8ae4
--- /dev/null
+++ b/src/js/views/LibraryAlbums.js
@@ -0,0 +1,54 @@
+
+import React, { PropTypes } from 'react'
+import { connect } from 'react-redux'
+import { bindActionCreators } from 'redux'
+import { Link } from 'react-router'
+
+import AlbumGrid from '../components/AlbumGrid'
+
+import * as mopidyActions from '../services/mopidy/actions'
+import * as spotifyActions from '../services/spotify/actions'
+
+class LibraryAlbums extends React.Component{
+
+ constructor(props) {
+ super(props);
+ }
+
+ // on render
+ componentDidMount(){
+ this.props.spotifyActions.getLibraryAlbums();
+ }
+
+ render(){
+ if( this.props.spotify.libraryAlbums ){
+ return (
+
+ );
+ }
+ return null;
+ }
+}
+
+
+/**
+ * Export our component
+ *
+ * We also integrate our global store, using connect()
+ **/
+
+const mapStateToProps = (state, ownProps) => {
+ return state;
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ mopidyActions: bindActionCreators(mopidyActions, dispatch),
+ spotifyActions: bindActionCreators(spotifyActions, dispatch)
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(LibraryAlbums)
\ No newline at end of file
diff --git a/src/js/views/LibraryArtists.js b/src/js/views/LibraryArtists.js
index 2203e3c1..13090caf 100755
--- a/src/js/views/LibraryArtists.js
+++ b/src/js/views/LibraryArtists.js
@@ -15,7 +15,7 @@ class LibraryArtists extends React.Component{
// on render
componentDidMount(){
- this.props.spotifyActions.loadLibraryArtists();
+ this.props.spotifyActions.getLibraryArtists();
}
render(){
diff --git a/src/js/views/LibraryTracks.js b/src/js/views/LibraryTracks.js
new file mode 100755
index 00000000..b78ea278
--- /dev/null
+++ b/src/js/views/LibraryTracks.js
@@ -0,0 +1,54 @@
+
+import React, { PropTypes } from 'react'
+import { connect } from 'react-redux'
+import { bindActionCreators } from 'redux'
+import { Link } from 'react-router'
+
+import TrackList from '../components/TrackList'
+
+import * as mopidyActions from '../services/mopidy/actions'
+import * as spotifyActions from '../services/spotify/actions'
+
+class LibraryTracks extends React.Component{
+
+ constructor(props) {
+ super(props);
+ }
+
+ // on render
+ componentDidMount(){
+ this.props.spotifyActions.getLibraryTracks();
+ }
+
+ render(){
+ if( this.props.spotify.libraryAlbums ){
+ return (
+
+
My tracks
+
+
+ );
+ }
+ return null;
+ }
+}
+
+
+/**
+ * Export our component
+ *
+ * We also integrate our global store, using connect()
+ **/
+
+const mapStateToProps = (state, ownProps) => {
+ return state;
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ mopidyActions: bindActionCreators(mopidyActions, dispatch),
+ spotifyActions: bindActionCreators(spotifyActions, dispatch)
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(LibraryTracks)
\ No newline at end of file