From ce4c26f18b59cae8f24768e80e308f0723b3c11a Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sat, 14 Jan 2017 22:32:39 +1300 Subject: [PATCH] Bunched action calls; Library artists and albums --- src/js/bootstrap.js | 4 -- src/js/components/ArtistSentence.js | 1 + src/js/services/spotify/actions.js | 39 ++++------------ src/js/services/spotify/middleware.js | 45 +++++++++++++++++++ src/js/services/ui/reducer.js | 62 ++++++++++++++++++++++++++ src/js/views/Album.js | 3 ++ src/js/views/Artist.js | 2 +- src/js/views/library/LibraryAlbums.js | 33 +++++++++----- src/js/views/library/LibraryArtists.js | 34 ++++++++------ 9 files changed, 164 insertions(+), 59 deletions(-) diff --git a/src/js/bootstrap.js b/src/js/bootstrap.js index e3611045..2ba1661b 100755 --- a/src/js/bootstrap.js +++ b/src/js/bootstrap.js @@ -65,10 +65,6 @@ var initialState = { playlists: [], tracks: [] }, - library_artists: [], - artists: [], - library_albums: [], - albums: [], library_playlists: [], playlists: [], notifications: [] diff --git a/src/js/components/ArtistSentence.js b/src/js/components/ArtistSentence.js index dfe527c6..f7e86273 100755 --- a/src/js/components/ArtistSentence.js +++ b/src/js/components/ArtistSentence.js @@ -16,6 +16,7 @@ export default class ArtistSentence extends React.Component{ { this.props.artists.map( (artist, index) => { + if (!artist) return - var separator = null; if( index == this.props.artists.length - 2 ){ separator = ' and '; diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 2df68464..860f45f3 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -666,31 +666,12 @@ export function getArtists( uris ){ export function getLibraryArtists(){ return (dispatch, getState) => { - - dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false }); - sendRequest( dispatch, getState, 'me/following?type=artist&limit=50' ) .then( response => { - for (var i = 0; i < response.length; i++){ - var artist = response[i] - for (var i = 0; i < artist.albums.length; i++){ - dispatch({ - type: 'ALBUM_LOADED', - album: artist.albums[i] - }); - } - artist.albums = helpers.asURIs(artist.albums) - artist.albums_more = artist.albums.next - dispatch({ - type: 'ARTIST_LOADED', - artist: artist - }); - } - dispatch({ - type: 'LIBRARY_ARTISTS_LOADED', - uris: helpers.asURIs(response) - }); + type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', + data: response + }) }); } } @@ -777,12 +758,10 @@ export function getAlbum( uri ){ // get all album artists as full objects sendRequest( dispatch, getState, 'artists/?ids='+artist_ids ) .then( response => { - for (var i = 0; i < response.artists.length; i++){ - dispatch({ - type: 'ARTIST_LOADED', - artist: response.artists[i] - }); - } + dispatch({ + type: 'ARTISTS_LOADED', + artists: response.artists + }); }); }) @@ -792,14 +771,14 @@ export function getAlbum( uri ){ export function getLibraryAlbums(){ return (dispatch, getState) => { - dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false }); + dispatch({ type: 'LIBRARY_ALBUMS_LOADED', uris: false }); sendRequest( dispatch, getState, 'me/albums?limit=40' ) .then( response => { dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: response - }); + }) }); } } diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index 4a078ae8..b8bb009e 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -93,6 +93,51 @@ const SpotifyMiddleware = (function(){ } break + case 'SPOTIFY_LIBRARY_ARTISTS_LOADED': + store.dispatch({ + type: 'ARTISTS_LOADED', + artists: action.data.artists.items + }); + store.dispatch({ + type: 'LIBRARY_ARTISTS_LOADED', + uris: helpers.asURIs(action.data.artists.items), + more: action.data.artists.next, + total: action.data.artists.total + }); + break + + case 'SPOTIFY_LIBRARY_ALBUMS_LOADED': + + var albums = [] + + for (var i = 0; i < action.data.items.length; i++){ + albums.push( + Object.assign( + {}, + action.data.items[i].album, + { + added_at: action.data.items[i].added_at, + tracks: action.data.items[i].album.tracks.items, + tracks_next: action.data.items[i].album.tracks.tracks_next, + tracks_total: action.data.items[i].album.tracks.tracks_total + } + ) + ) + } + + store.dispatch({ + type: 'ALBUMS_LOADED', + albums: albums + }); + + store.dispatch({ + type: 'LIBRARY_ALBUMS_LOADED', + uris: helpers.asURIs(albums), + more: action.data.next, + total: action.data.total + }); + break + // This action is irrelevant to us, pass it on to the next middleware default: return next(action); diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index bd0509ba..9defb420 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -129,6 +129,19 @@ export default function reducer(ui = {}, action){ * Albums **/ + case 'ALBUMS_LOADED': + var albums = Object.assign([], ui.albums) + + for (var i = 0; i < action.albums.length; i++){ + var album = action.albums[i] + if (typeof(albums[album.uri]) !== 'undefined'){ + artist = Object.assign({}, albums[album.uri], album) + } + albums[album.uri] = album + } + + return Object.assign({}, ui, { albums: albums }); + case 'ALBUM_LOADED': var albums = Object.assign([], ui.albums) var album = Object.assign({}, action.album) @@ -172,12 +185,43 @@ export default function reducer(ui = {}, action){ var album = Object.assign({}, ui.album, { following: action.is_following }) return Object.assign({}, ui, { album: album, following_loading: false }); + case 'LIBRARY_ALBUMS_LOADED': + if (!action.uris){ + return Object.assign({}, ui, { + library_albums: null, + library_albums_more: null, + library_albums_total: null + }); + } + + var library_albums = [] + if (ui.library_albums) library_albums = Object.assign([], ui.library_albums) + + return Object.assign({}, ui, { + library_albums: [...library_albums, ...action.uris], + library_albums_more: action.more, + library_albums_total: action.total + }); + /** * Artists **/ + case 'ARTISTS_LOADED': + var artists = Object.assign([], ui.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) + } + artists[artist.uri] = artist + } + + return Object.assign({}, ui, { artists: artists }); + case 'ARTIST_LOADED': var artists = Object.assign([], ui.artists) var artist = Object.assign({}, action.artist) @@ -215,6 +259,24 @@ export default function reducer(ui = {}, action){ var artist = Object.assign({}, ui.artist, { following: action.is_following }) return Object.assign({}, ui, { artist: artist, following_loading: false }); + case 'LIBRARY_ARTISTS_LOADED': + if (!action.uris){ + return Object.assign({}, ui, { + library_artists: null, + library_artists_more: null, + library_artists_total: null + }); + } + + var library_artists = [] + if (ui.library_artists) library_artists = Object.assign([], ui.library_artists) + + return Object.assign({}, ui, { + library_artists: [...library_artists, ...action.uris], + library_artists_more: action.more, + library_artists_total: action.total + }); + /** * User diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 4e4e5cc8..5054565e 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -43,6 +43,9 @@ class Album extends React.Component{ } loadAlbum( props = this.props ){ + // if we've already loaded the full version of this album, halt! + if (this.props.album && this.props.album.tracks) return false + switch( helpers.uriSource( props.params.uri ) ){ case 'spotify': diff --git a/src/js/views/Artist.js b/src/js/views/Artist.js index 85b9d10b..90d1680a 100755 --- a/src/js/views/Artist.js +++ b/src/js/views/Artist.js @@ -223,8 +223,8 @@ class Artist extends React.Component{ const mapStateToProps = (state, ownProps) => { return { + artist: (state.ui.artists && typeof(state.ui.artists[ownProps.params.uri]) !== 'undefined' ? state.ui.artists[ownProps.params.uri] : false ), artists: state.ui.artists, - artist: state.ui.artists[ownProps.params.uri], albums: state.ui.albums, spotify_authorized: state.spotify.authorized, mopidy_connected: state.mopidy.connected diff --git a/src/js/views/library/LibraryAlbums.js b/src/js/views/library/LibraryAlbums.js index b3f731c7..2a383fb2 100755 --- a/src/js/views/library/LibraryAlbums.js +++ b/src/js/views/library/LibraryAlbums.js @@ -24,16 +24,16 @@ class LibraryAlbums extends React.Component{ } componentDidMount(){ - this.props.spotifyActions.getLibraryAlbums(); + if (!this.props.library_albums) this.props.spotifyActions.getLibraryAlbums(); } loadMore(){ - if( !this.props.albums_more ) return - this.props.spotifyActions.getURL( this.props.albums_more, 'SPOTIFY_LIBRARY_ALBUMS_LOADED_MORE' ); + if( !this.props.library_albums_more ) return + this.props.spotifyActions.getURL( this.props.library_albums_more, 'SPOTIFY_LIBRARY_ALBUMS_LOADED' ); } - renderView(){ - if( !this.props.albums ) return null + renderView(albums){ + if (!albums || albums.length <= 0) return null if( this.props.view == 'list' ){ var columns = [ @@ -60,20 +60,20 @@ class LibraryAlbums extends React.Component{ ] return (
- +
) }else if( this.props.view == 'thumbnails' ){ return (
- { this.props.albums ? : null } +
) }else{ return (
{ - this.props.albums.map( album => { + albums.map( album => { return (
@@ -96,6 +96,16 @@ class LibraryAlbums extends React.Component{ } render(){ + var albums = [] + + if (this.props.library_albums && this.props.albums){ + for (var i = 0; i < this.props.library_albums.length; i++){ + var uri = this.props.library_albums[i] + if (this.props.albums.hasOwnProperty(uri)){ + albums.push(this.props.albums[uri]) + } + } + } var view_options = [ { @@ -119,7 +129,7 @@ class LibraryAlbums extends React.Component{ return (
- { this.renderView() } + { this.renderView(albums) } this.loadMore() }/>
); @@ -136,8 +146,9 @@ class LibraryAlbums extends React.Component{ const mapStateToProps = (state, ownProps) => { return { view: state.ui.library_albums_view, - albums: state.spotify.library_albums, - albums_more: state.spotify.library_albums_more, + albums: state.ui.albums, + library_albums: state.ui.library_albums, + library_albums_more: state.ui.library_albums_more, } } diff --git a/src/js/views/library/LibraryArtists.js b/src/js/views/library/LibraryArtists.js index cad25853..9fa69475 100755 --- a/src/js/views/library/LibraryArtists.js +++ b/src/js/views/library/LibraryArtists.js @@ -20,19 +20,16 @@ class LibraryArtists extends React.Component{ super(props); } - // on render componentDidMount(){ - this.props.spotifyActions.getLibraryArtists(); + if (!this.props.library_artists) this.props.spotifyActions.getLibraryArtists(); } loadMore(){ - if( !this.props.artists_more ) return - this.props.spotifyActions.getURL( this.props.artists_more, 'SPOTIFY_LIBRARY_ARTISTS_LOADED_MORE' ); + if( !this.props.library_artists_more ) return + this.props.spotifyActions.getURL( this.props.library_artists_more, 'SPOTIFY_LIBRARY_ARTISTS_LOADED' ); } - renderView(){ - if( !this.props.artists ) return null - + renderView(artists){ if( this.props.view == 'list' ){ var columns = [ { @@ -48,13 +45,13 @@ class LibraryArtists extends React.Component{ ] return (
- +
) }else{ return (
- +
) } @@ -62,6 +59,16 @@ class LibraryArtists extends React.Component{ render(){ + var artists = [] + if (this.props.library_artists && this.props.artists){ + for (var i = 0; i < this.props.library_artists.length; i++){ + var uri = this.props.library_artists[i] + if (this.props.artists.hasOwnProperty(uri)){ + artists.push(this.props.artists[uri]) + } + } + } + var view_options = [ { value: 'thumbnails', @@ -80,7 +87,7 @@ class LibraryArtists extends React.Component{ return (
- { this.renderView() } + { this.renderView(artists) } this.loadMore() }/>
); @@ -96,9 +103,10 @@ class LibraryArtists extends React.Component{ const mapStateToProps = (state, ownProps) => { return { - view: state.ui.library_artists_view, - artists: state.spotify.library_artists, - artists_more: state.spotify.library_artists_more + artists: state.ui.artists, + library_artists: state.ui.library_artists, + library_artists_more: state.ui.library_artists_more, + view: state.ui.library_artists_view } }