Bunched action calls; Library artists and albums

This commit is contained in:
James Barnsley
2017-01-14 22:32:39 +13:00
parent 539748b112
commit ce4c26f18b
9 changed files with 164 additions and 59 deletions

4
src/js/bootstrap.js vendored
View File

@ -65,10 +65,6 @@ var initialState = {
playlists: [],
tracks: []
},
library_artists: [],
artists: [],
library_albums: [],
albums: [],
library_playlists: [],
playlists: [],
notifications: []

View File

@ -16,6 +16,7 @@ export default class ArtistSentence extends React.Component{
<span className={ this.props.className ? this.props.className+" artist-sentence" : "artist-sentence" }>
{
this.props.artists.map( (artist, index) => {
if (!artist) return <span>-</span>
var separator = null;
if( index == this.props.artists.length - 2 ){
separator = ' and ';

View File

@ -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
});
})
});
}
}

View File

@ -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);

View File

@ -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

View File

@ -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':

View File

@ -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

View File

@ -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 (
<section className="list-wrapper">
<List rows={this.props.albums} columns={columns} link_prefix={global.baseURL+"album/"} />
<List rows={albums} columns={columns} link_prefix={global.baseURL+"album/"} />
</section>
)
}else if( this.props.view == 'thumbnails' ){
return (
<section className="grid-wrapper">
{ this.props.albums ? <AlbumGrid albums={this.props.albums} /> : null }
<AlbumGrid albums={albums} />
</section>
)
}else{
return (
<section className="grid-wrapper albums-detail-subview">
{
this.props.albums.map( album => {
albums.map( album => {
return (
<div className="album" key={album.uri}>
<Link to={global.baseURL+'album/'+album.uri}>
@ -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 (
<div className="view library-albums-view">
<Header icon="cd" title="My albums" actions={actions} />
{ this.renderView() }
{ this.renderView(albums) }
<LazyLoadListener loadMore={ () => this.loadMore() }/>
</div>
);
@ -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,
}
}

View File

@ -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 (
<section className="list-wrapper">
<List rows={this.props.artists} columns={columns} link_prefix={global.baseURL+"artist/"} show_source_icon={true} />
<List rows={artists} columns={columns} link_prefix={global.baseURL+"artist/"} show_source_icon={true} />
</section>
)
}else{
return (
<section className="grid-wrapper">
<ArtistGrid artists={this.props.artists} />
<ArtistGrid artists={artists} />
</section>
)
}
@ -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 (
<div className="view library-artists-view">
<Header icon="mic" title="My artists" actions={actions} />
{ this.renderView() }
{ this.renderView(artists) }
<LazyLoadListener loadMore={ () => this.loadMore() }/>
</div>
);
@ -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
}
}