diff --git a/src/js/services/core/middleware.js b/src/js/services/core/middleware.js index bbd292c8..23a12625 100755 --- a/src/js/services/core/middleware.js +++ b/src/js/services/core/middleware.js @@ -15,6 +15,7 @@ const CoreMiddleware = (function(){ * The actual middleware inteceptor **/ return store => next => action => { + var core = store.getState().core; switch(action.type){ @@ -102,68 +103,6 @@ const CoreMiddleware = (function(){ next(action) break - case 'TRACK_LOADED': - if (action.data) ReactGA.event({ category: 'Track', action: 'Load', label: action.key }); - - if (action.track.album && action.track.album.images && action.track.album.images.length > 0){ - action.track.album.images = helpers.digestMopidyImages(store.getState().mopidy, action.track.album.images); - } - - next(action) - break - - case 'ALBUM_LOADED': - if (action.data) ReactGA.event({ category: 'Album', action: 'Load', label: action.key }) - - if (action.album.images && action.album.images.length > 0){ - action.album.images = helpers.digestMopidyImages(store.getState().mopidy, action.album.images); - } - - // Load our tracks - if (action.album.tracks){ - store.dispatch({ - type: 'TRACKS_LOADED', - tracks: action.album.tracks - }); - } - - next(action) - break - - case 'ALBUMS_LOADED': - if (action.data) ReactGA.event({ category: 'Albums', action: 'Load', label: action.albums.length+' items' }) - - for (var i = 0; i < action.albums.length; i++){ - if (action.albums[i].images && action.albums[i].images.length > 0){ - action.albums[i].images = helpers.digestMopidyImages(store.getState().mopidy, action.albums[i].images); - } - - // Load our tracks - if (action.albums[i].tracks){ - store.dispatch({ - type: 'TRACKS_LOADED', - tracks: action.albums[i].tracks - }); - } - } - - next(action) - break - - case 'ARTIST_LOADED': - if (action.data) ReactGA.event({ category: 'Artist', action: 'Load', label: action.artist.uri }); - - // Load our tracks - if (action.artist.tracks){ - store.dispatch({ - type: 'TRACKS_LOADED', - tracks: action.artist.tracks - }); - } - - next(action) - break - case 'PLAY_PLAYLIST': ReactGA.event({ category: 'Playlist', action: 'Play', label: action.uri }) next(action) @@ -248,35 +187,6 @@ const CoreMiddleware = (function(){ next(action) break - case 'PLAYLIST_LOADED': - if (action.data) ReactGA.event({ category: 'Playlist', action: 'Load', label: action.playlist.uri }) - - var playlist = Object.assign({}, action.playlist) - switch (helpers.uriSource(playlist.uri)){ - - case 'm3u': - playlist.can_edit = true - break - - case 'spotify': - if (store.getState().spotify.authorization && store.getState().spotify.me){ - playlist.can_edit = (helpers.getFromUri('playlistowner',playlist.uri) == store.getState().spotify.me.id) - } - } - - // Load our tracks - if (action.playlist.tracks){ - store.dispatch({ - type: 'TRACKS_LOADED', - tracks: action.playlist.tracks - }); - } - - // proceed as usual - action.playlist = playlist; - next(action); - break - case 'MOPIDY_CURRENTTLTRACK': if (action.data && action.data.track){ helpers.setWindowTitle(action.data.track, store.getState().mopidy.play_state); @@ -293,8 +203,22 @@ const CoreMiddleware = (function(){ } } - next(action) - break + var current_tracklist = [] + Object.assign(current_tracklist, core.current_tracklist) + + for (var i = 0; i < current_tracklist.length; i++){ + Object.assign( + current_tracklist[i], + { playing: (current_tracklist[i].tlid == action.data.tlid) } + ) + } + + // Update action + action.current_tracklist = current_tracklist; + action.current_track = action.data.track.uri; + + next(action); + break; case 'MOPIDY_TLTRACKS': @@ -376,6 +300,230 @@ const CoreMiddleware = (function(){ location.reload() break + + /** + * Index actions + * These modify our asset indexes, which are used globally + **/ + + case 'TRACK_LOADED': + if (action.track.album && action.track.album.images && action.track.album.images.length > 0){ + action.track.album.images = helpers.digestMopidyImages(store.getState().mopidy, action.track.album.images); + } + + var tracks = Object.assign({}, core.tracks) + if (tracks[action.key]){ + var track = Object.assign( + {}, + tracks[action.key], + helpers.formatTracks(action.track) + ); + } else { + var track = Object.assign( + {}, + helpers.formatTracks(action.track) + ); + } + + // Update index + tracks[action.key] = track; + store.dispatch({ + type: 'UPDATE_TRACKS_INDEX', + tracks: tracks + }); + + next(action); + break; + + case 'TRACKS_LOADED': + for (var i = 0; i < action.tracks.length; i++){ + store.dispatch({ + type: 'TRACK_LOADED', + key: action.tracks[i].uri, + track: action.tracks[i] + }); + } + next(action); + break; + + case 'ALBUM_LOADED': + var albums = Object.assign({}, core.albums) + + if (albums[action.key]){ + var album = Object.assign({}, albums[action.key], action.album) + } else { + var album = Object.assign({}, action.album) + } + + if (action.album.images && action.album.images.length > 0){ + action.album.images = helpers.digestMopidyImages(store.getState().mopidy, action.album.images); + } + + // Load our tracks + if (album.tracks){ + var tracks = helpers.formatTracks(album.tracks); + var tracks_uris = helpers.arrayOf('uri', tracks); + album.tracks_uris = tracks_uris; + delete album.tracks; + + store.dispatch({ + type: 'TRACKS_LOADED', + tracks: tracks + }); + } + + // Update index + albums[action.key] = album; + store.dispatch({ + type: 'UPDATE_ALBUMS_INDEX', + albums: albums + }); + + next(action); + break; + + case 'ALBUMS_LOADED': + for (var i = 0; i < action.albums.length; i++){ + store.dispatch({ + type: 'ALBUM_LOADED', + key: action.albums[i].uri, + album: action.albums[i] + }); + } + next(action); + break + + case 'ARTIST_LOADED': + var artists = Object.assign({}, core.artists) + + if (artists[action.key]){ + + // if we've already got images, remove and add as additional_images + // this is to prevent LastFM overwriting Spotify images + if (artists[action.key].images){ + action.artist.images_additional = action.artist.images + delete action.artist.images + } + + var artist = Object.assign({}, artists[action.key], action.artist) + if (artist.tracks){ + artist.tracks = helpers.formatTracks(artist.tracks); + } + } else { + var artist = Object.assign({}, action.artist) + if (artist.tracks){ + artist.tracks = helpers.formatTracks(artist.tracks); + } + } + + // Load our tracks + if (artist.tracks){ + store.dispatch({ + type: 'TRACKS_LOADED', + tracks: artist.tracks + }); + } + + // Update index + artists[action.key] = artist; + store.dispatch({ + type: 'UPDATE_ARTISTS_INDEX', + artists: artists + }); + + next(action); + break; + + case 'ARTISTS_LOADED': + for (var i = 0; i < action.artists.length; i++){ + store.dispatch({ + type: 'ARTIST_LOADED', + key: action.artists[i].uri, + artist: action.artists[i] + }); + } + next(action); + break; + + case 'PLAYLIST_LOADED': + var playlist = Object.assign({}, action.playlist); + var playlists = Object.assign({}, core.playlists); + + // Detect editability + switch (helpers.uriSource(playlist.uri)){ + + case 'm3u': + playlist.can_edit = true + break + + case 'spotify': + if (store.getState().spotify.authorization && store.getState().spotify.me){ + playlist.can_edit = (helpers.getFromUri('playlistowner',playlist.uri) == store.getState().spotify.me.id) + } + } + + if (playlists[action.key] !== undefined){ + var existing_playlist = playlists[action.key]; + + if (existing_playlist.tracks && playlist.tracks){ + var tracks = [...existing_playlist.tracks, ...playlist.tracks]; + } else if (existing_playlist.tracks){ + var tracks = existing_playlist.tracks; + } else if (action.playlist.tracks){ + var tracks = playlist.tracks; + } else { + var tracks = []; + } + + playlist = Object.assign( + {}, + existing_playlist, + playlist + ) + } + + // Load our tracks + if (playlist.tracks){ + var tracks = helpers.formatTracks(playlist.tracks); + var tracks_uris = helpers.arrayOf('uri', tracks); + playlist.tracks_uris = tracks_uris; + delete playlist.tracks; + + store.dispatch({ + type: 'TRACKS_LOADED', + tracks: tracks + }); + } + + // Update index + playlists[action.key] = playlist; + store.dispatch({ + type: 'UPDATE_PLAYLISTS_INDEX', + playlists: playlists + }); + + next(action); + break; + + case 'USER_LOADED': + var users = Object.assign([], core.users) + + if (users[action.key]){ + var user = Object.assign({}, users[action.key], action.user) + } else { + var user = Object.assign({}, action.user) + } + + // Update index + users[action.key] = user; + store.dispatch({ + type: 'UPDATE_USERS_INDEX', + users: users + }); + + next(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/core/reducer.js b/src/js/services/core/reducer.js index c258c2f3..05f496f6 100755 --- a/src/js/services/core/reducer.js +++ b/src/js/services/core/reducer.js @@ -18,60 +18,14 @@ export default function reducer(core = {}, action){ return Object.assign({}, core, { current_tracklist: action.tracklist }); case 'MOPIDY_CURRENTTLTRACK': - if (!action.data) return core - - var current_tracklist = [] - Object.assign(current_tracklist, core.current_tracklist) - - for (var i = 0; i < current_tracklist.length; i++){ - Object.assign( - current_tracklist[i], - { playing: (current_tracklist[i].tlid == action.data.tlid ) } - ) + if (!action.data){ + return core; } - return Object.assign({}, core, { - current_tracklist: current_tracklist, - current_track: action.data.track.uri + current_tracklist: action.current_tracklist, + current_track: action.current_track }); - case 'TRACK_LOADED': - if (!action.key || !action.track) return core - - var tracks = Object.assign({}, core.tracks) - if (tracks[action.key]){ - var track = Object.assign( - {}, - tracks[action.key], - helpers.formatTracks(action.track) - ); - } else { - var track = Object.assign( - {}, - helpers.formatTracks(action.track) - ); - } - - tracks[action.key] = track - return Object.assign({}, core, { tracks: tracks }); - - case 'TRACKS_LOADED': - var tracks = Object.assign({}, core.tracks) - - for (var i = 0; i < action.tracks.length; i++){ - var track = action.tracks[i] - if (tracks[track.uri] !== undefined){ - track = Object.assign( - {}, - tracks[track.uri], - track - ); - } - tracks[track.uri] = helpers.formatTracks(track); - } - - return Object.assign({}, core, { tracks: tracks }); - case 'PUSHER_QUEUE_METADATA': case 'PUSHER_QUEUE_METADATA_CHANGED': var tracklist = Object.assign([], core.current_tracklist) @@ -153,37 +107,27 @@ export default function reducer(core = {}, action){ /** - * Albums + * Index updates + * These actions are only ever called by middleware after we've digested one more many assets + * and appended to their relevant index. **/ - case 'ALBUM_LOADED': - var albums = Object.assign([], core.albums) + case 'UPDATE_TRACKS_INDEX': + return Object.assign({}, core, { tracks: action.tracks }); - if (albums[action.key]){ - var album = Object.assign({}, albums[action.key], action.album) - } else { - var album = Object.assign({}, action.album) - } + case 'UPDATE_ALBUMS_INDEX': + return Object.assign({}, core, { albums: action.albums }); - album.tracks = helpers.formatTracks(album.tracks); - albums[action.key] = album + case 'UPDATE_ARTISTS_INDEX': + return Object.assign({}, core, { artists: action.artists }); - return Object.assign({}, core, { albums: albums }); + case 'UPDATE_PLAYLISTS_INDEX': + return Object.assign({}, core, { playlists: action.playlists }); - case 'ALBUMS_LOADED': - var albums = Object.assign([], core.albums) + case 'UPDATE_USERS_INDEX': + return Object.assign({}, core, { users: action.users }); - for (var i = 0; i < action.albums.length; i++){ - var album = action.albums[i] - if (albums[album.uri]){ - album = Object.assign({}, albums[album.uri], album) - } - album.tracks = helpers.formatTracks(album.tracks); - albums[album.uri] = album - } - - return Object.assign({}, core, { albums: albums }); case 'NEW_RELEASES_LOADED': if (!action.uris){ @@ -204,54 +148,6 @@ export default function reducer(core = {}, action){ }); - - /** - * Artists - **/ - - case 'ARTIST_LOADED': - var artists = Object.assign([], core.artists) - - if (artists[action.key]){ - - // if we've already got images, remove and add as additional_images - // this is to prevent LastFM overwriting Spotify images - if (artists[action.key].images){ - action.artist.images_additional = action.artist.images - delete action.artist.images - } - - var artist = Object.assign({}, artists[action.key], action.artist) - if (artist.tracks){ - artist.tracks = helpers.formatTracks(artist.tracks); - } - } else { - var artist = Object.assign({}, action.artist) - if (artist.tracks){ - artist.tracks = helpers.formatTracks(artist.tracks); - } - } - - artists[action.key] = artist - return Object.assign({}, core, { artists: artists }); - - case 'ARTISTS_LOADED': - var artists = Object.assign([], core.artists) - - for (var i = 0; i < action.artists.length; i++){ - var artist = action.artists[i] - if (typeof(artists[artist.uri]) !== 'undefined'){ - artist = Object.assign({}, artists[artist.uri], artist) - } - - if (artist.tracks){ - artist.tracks = helpers.formatTracks(artist.tracks); - } - artists[artist.uri] = artist - } - - return Object.assign({}, core, { artists: artists }); - case 'ARTIST_ALBUMS_LOADED': var artists = Object.assign([], core.artists) var albums_uris = [] @@ -270,22 +166,6 @@ export default function reducer(core = {}, action){ return Object.assign({}, core, { artists: artists }); - /** - * User profiles - **/ - - case 'USER_LOADED': - var users = Object.assign([], core.users) - - if (users[action.key]){ - var user = Object.assign({}, users[action.key], action.user) - } else { - var user = Object.assign({}, action.user) - } - - users[action.key] = user - return Object.assign({}, core, { users: users }); - case 'USER_PLAYLISTS_LOADED': var users = Object.assign([], core.users) var playlists_uris = [] @@ -310,38 +190,6 @@ export default function reducer(core = {}, action){ * Playlists **/ - case 'PLAYLIST_LOADED': - case 'PLAYLIST_UPDATED': - var playlists = Object.assign([], core.playlists) - - if (typeof(playlists[action.key]) !== 'undefined'){ - var existing_playlist = Object.assign({}, playlists[action.key]) - - if (existing_playlist.tracks && action.playlist.tracks){ - var tracks = [...existing_playlist.tracks, ...action.playlist.tracks] - } else if (existing_playlist.tracks){ - var tracks = existing_playlist.tracks - } else if (action.playlist.tracks){ - var tracks = action.playlist.tracks - } else { - var tracks = [] - } - - var merged_playlist = Object.assign( - {}, - existing_playlist, - action.playlist, - { - tracks: helpers.formatTracks(tracks) - } - ) - } else { - var merged_playlist = Object.assign({}, action.playlist) - } - - playlists[action.key] = merged_playlist - return Object.assign({}, core, { playlists: playlists }) - case 'PLAYLIST_KEY_UPDATED': var playlists = Object.assign([], core.playlists) @@ -355,43 +203,6 @@ export default function reducer(core = {}, action){ delete playlists[action.key] playlists[playlist.uri] = playlist - return Object.assign({}, core, { playlists: playlists }) - - case 'PLAYLISTS_LOADED': - var playlists = Object.assign([], core.playlists) - - for (var i = 0; i < action.playlists.length; i++){ - var loaded_playlist = action.playlists[i] - - if (typeof(playlists[loaded_playlist.uri]) !== 'undefined'){ - var existing_playlist = Object.assign({}, playlists[loaded_playlist.uri]) - - if (existing_playlist.tracks && loaded_playlist.tracks){ - var tracks = [...existing_playlist.tracks, ...loaded_playlist.tracks] - } else if (existing_playlist.tracks){ - var tracks = existing_playlist.tracks - } else if (loaded_playlist.tracks){ - var tracks = loaded_playlist.tracks - } else { - var tracks = [] - } - - var merged_playlist = Object.assign( - {}, - existing_playlist, - loaded_playlist, - { - tracks: helpers.formatTracks(tracks) - } - ) - - } else { - var merged_playlist = loaded_playlist - } - - playlists[merged_playlist.uri] = merged_playlist - } - return Object.assign({}, core, { playlists: playlists }); case 'PLAYLIST_LOADED_MORE_TRACKS': diff --git a/src/js/services/lastfm/actions.js b/src/js/services/lastfm/actions.js index a65f1546..17e35954 100755 --- a/src/js/services/lastfm/actions.js +++ b/src/js/services/lastfm/actions.js @@ -161,10 +161,13 @@ export function connect(){ // Not authorized? Just use a generic lookup to test our connection } else { - sendRequest(dispatch, getState, 'method=artist.getInfo&artist=') + sendRequest(dispatch, getState, 'method=artist.getInfo&artist=Moby') .then( response => { dispatch({ type: 'LASTFM_CONNECTED' }) + }, + error => { + dispatch({ type: 'LASTFM_DISCONNECTED' }) } ) } diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 1ada9e4c..f24df0b0 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -120,6 +120,16 @@ class Album extends React.Component{ } } + var tracks = []; + if (this.props.album.tracks_uris && this.props.tracks){ + for (var i = 0; i < this.props.album.tracks_uris.length; i++){ + var uri = this.props.album.tracks_uris[i] + if (this.props.tracks.hasOwnProperty(uri)){ + tracks.push(this.props.tracks[uri]) + } + } + } + return (
@@ -135,8 +145,7 @@ class Album extends React.Component{ { !this.props.slim_mode && artists.length > 0 ?
  • : null } { this.props.album.release_date ?
  • : null }
  • - { this.props.album.tracks_total ? this.props.album.tracks_total : '0' } tracks,  - { this.props.album.tracks ? : '0 mins' } + {tracks ? {tracks.length} tracks, : '0 tracks, 0 mins' }
  • @@ -148,7 +157,7 @@ class Album extends React.Component{
    - { this.props.album.tracks ? : null } + this.loadMore() }/>
    @@ -169,6 +178,7 @@ const mapStateToProps = (state, ownProps) => { return { slim_mode: state.ui.slim_mode, load_queue: state.ui.load_queue, + tracks: state.core.tracks, artists: state.core.artists, album: (state.core.albums && state.core.albums[uri] !== undefined ? state.core.albums[uri] : false ), albums: state.core.albums,