Following; PLAYLISTS_LOADED; Full index

This commit is contained in:
James Barnsley
2017-01-15 11:40:08 +13:00
parent ce4c26f18b
commit 8b15e024cd
11 changed files with 269 additions and 171 deletions

View File

@ -23,8 +23,9 @@ export default class ArtistSentence extends React.Component{
}else if( index < this.props.artists.length - 2 ){
separator = ', ';
}
if( !artist.name ) artist.name = '-'
if( artist.uri ){
if (!artist.name){
var content = <span>-</span>
} else if (artist.uri){
var content = <Link className="artist" to={global.baseURL+'artist/'+artist.uri}>{ artist.name }</Link>
}else{
var content = <span>{ artist.name }</span>

View File

@ -30,23 +30,8 @@ class FollowButton extends React.Component{
render(){
if( !this.props.spotify_authorized || !this.props.uri ) return false
var item = {}
switch (helpers.uriType( this.props.uri )){
case 'artist':
item = this.props.artists[this.props.uri]
break
case 'user':
item = this.props.users[this.props.uri]
break
case 'album':
item = this.props.albums[this.props.uri]
break
case 'playlist':
item = this.props.playlists[this.props.uri]
break
}
if( item.following === true ){
if( this.props.is_following === true ){
return <button className="tertiary large" onClick={ () => this.remove() }>{ this.props.removeText }</button>
}else{
return <button className="tertiary large" onClick={ () => this.add() }>{ this.props.addText }</button>
@ -56,11 +41,7 @@ class FollowButton extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
spotify_authorized: state.spotify.authorized,
artists: state.ui.artists,
users: state.ui.users,
albums: state.ui.albums,
playlists: state.ui.playlists
spotify_authorized: state.spotify.authorized
}
}

View File

@ -313,7 +313,11 @@ const MopidyMiddleware = (function(){
}
)
store.dispatch({ type: 'PLAYLIST_LOADED', playlist: playlist })
store.dispatch({
type: 'PLAYLIST_LOADED',
uri: playlist.uri,
playlist: playlist
})
})
}
})
@ -336,7 +340,11 @@ const MopidyMiddleware = (function(){
// tracks? get the full track objects
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_RESOLVE_PLAYLIST_TRACKS', tracks: playlist.tracks, uri: response.uri })
store.dispatch({ type: 'PLAYLIST_LOADED', playlist: playlist })
store.dispatch({
type: 'PLAYLIST_LOADED',
uri: playlist.uri,
playlist: playlist
})
})
break;
@ -367,7 +375,11 @@ const MopidyMiddleware = (function(){
}
}
store.dispatch({ type: 'PLAYLIST_TRACKS', tracks: tracks, uri: action.uri })
store.dispatch({
type: 'PLAYLIST_TRACKS',
tracks: tracks,
uri: action.uri
})
})
break
@ -425,7 +437,11 @@ const MopidyMiddleware = (function(){
var playlist = Object.assign({}, response, { name: action.name })
instruct( socket, store, 'playlists.save', { playlist: playlist } )
.then( response => {
store.dispatch({ type: 'PLAYLIST_UPDATED', uri: action.uri, playlist: playlist })
store.dispatch({
type: 'PLAYLIST_UPDATED',
uri: action.uri,
playlist: playlist
})
})
});
break

View File

@ -355,14 +355,11 @@ export function getCategory( id ){
export function getNewReleases(){
return (dispatch, getState) => {
dispatch({ type: 'SPOTIFY_NEW_RELEASES_LOADED', data: false });
sendRequest( dispatch, getState, 'browse/new-releases?country='+getState().spotify.country+'&limit=50' )
.then( response => {
dispatch({
type: 'SPOTIFY_NEW_RELEASES_LOADED',
data: response.albums
data: response
});
});
}
@ -405,8 +402,6 @@ export function getSearchResults( query, type = 'album,artist,playlist,track', l
export function following(uri, method = 'GET'){
return (dispatch, getState) => {
dispatch({ type: 'FOLLOWING_LOADING' });
if( method == 'PUT' ) var is_following = true
if( method == 'DELETE' ) var is_following = false
@ -450,7 +445,8 @@ export function following(uri, method = 'GET'){
if( response ) is_following = response
if( typeof(is_following) === 'object' ) is_following = is_following[0]
dispatch({
type: asset_name.toUpperCase()+'_FOLLOWING_LOADED',
type: 'SPOTIFY_'+asset_name.toUpperCase()+'_FOLLOWING_LOADED',
uri: uri,
is_following: is_following
});
});
@ -603,31 +599,29 @@ export function getArtist( uri ){
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' )
.then( response => {
for (var i = 0; i < response.artists.length; i++){
dispatch({
type: 'ARTIST_LOADED',
artist: response.artists[i]
});
}
Object.assign(artist, { related_artists: helpers.asURIs(response.artists) });
}),
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' )
.then( response => {
for (var i = 0; i < response.items.length; i++){
dispatch({
type: 'ALBUM_LOADED',
album: response.items[i]
});
}
Object.assign(artist, { albums: helpers.asURIs(response.items), albums_more: response.next });
dispatch({
type: 'ARTISTS_LOADED',
artists: response.artists
});
Object.assign(artist, { related_artists_uris: helpers.asURIs(response.artists) });
})
).then( () => {
dispatch({
type: 'ARTIST_LOADED',
uri: artist.uri,
artist: artist
});
// now go get our artist albums
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' )
.then( response => {
dispatch({
type: 'SPOTIFY_ARTIST_ALBUMS_LOADED',
data: response,
uri: uri
});
})
});
}
}
@ -732,19 +726,34 @@ export function getAlbum( uri ){
sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) )
.then( response => {
// dispatch our loaded artists (simple objects)
dispatch({
type: 'ARTISTS_LOADED',
artists: response.artists
});
var album = Object.assign(
{},
response,
{
artists: helpers.asURIs(response.artists),
artists_uris: helpers.asURIs(response.artists),
tracks: response.tracks.items,
tracks_more: response.tracks.next,
tracks_total: response.tracks.total
}
)
// add our album to all the tracks
for (var i = 0; i < album.tracks.length; i++){
album.tracks[i].album = {
name: album.name,
uri: album.uri
}
}
dispatch({
type: 'ALBUM_LOADED',
uri: album.uri,
album: album
});
@ -854,6 +863,7 @@ export function getPlaylist( uri ){
dispatch({
type: 'PLAYLIST_LOADED',
uri: playlist.uri,
playlist: playlist
})
})
@ -868,38 +878,15 @@ function loadNextPlaylistsBatch( dispatch, getState, playlists, lastResponse ){
loadNextPlaylistsBatch( dispatch, getState, playlists, response )
});
}else{
for( var i = 0; i < playlists.length; i++ ){
var playlist = Object.assign(
{},
playlists[i],
{
can_edit: (getState().spotify.authorized && getState().spotify.me && playlists[i].owner.id == getState().spotify.me.id),
tracks_total: playlists[i].tracks.total
}
)
// remove our tracklist. It'll overwrite any full records otherwise
delete playlist.tracks
dispatch({
type: 'PLAYLIST_LOADED',
playlist: playlist
});
}
dispatch({
type: 'LIBRARY_PLAYLISTS_LOADED',
uris: helpers.asURIs(playlists)
type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED',
playlists: playlists
});
}
}
export function getAllLibraryPlaylists(){
return (dispatch, getState) => {
dispatch({ type: 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED', data: false });
sendRequest( dispatch, getState, 'me/playlists?limit=50' )
.then( response => {
loadNextPlaylistsBatch( dispatch, getState, response.items, response )

View File

@ -93,6 +93,92 @@ const SpotifyMiddleware = (function(){
}
break
case 'SPOTIFY_PLAYLIST_FOLLOWING_LOADED':
store.dispatch({
type: 'PLAYLIST_LOADED',
uri: action.uri,
playlist: {
is_following: action.is_following
}
});
break
case 'SPOTIFY_ALBUM_FOLLOWING_LOADED':
store.dispatch({
type: 'ALBUM_LOADED',
uri: action.uri,
album: {
is_following: action.is_following
}
});
break
case 'SPOTIFY_ARTIST_FOLLOWING_LOADED':
store.dispatch({
type: 'ARTIST_LOADED',
uri: action.uri,
artist: {
is_following: action.is_following
}
});
break
case 'SPOTIFY_NEW_RELEASES_LOADED':
store.dispatch({
type: 'ALBUMS_LOADED',
albums: action.data.albums.items
});
store.dispatch({
type: 'NEW_RELEASES_LOADED',
uris: helpers.asURIs(action.data.albums.items),
more: action.data.albums.next,
total: action.data.albums.total
});
break
case 'SPOTIFY_ARTIST_ALBUMS_LOADED':
store.dispatch({
type: 'ALBUMS_LOADED',
albums: action.data.items
});
store.dispatch({
type: 'ARTIST_ALBUMS_LOADED',
uri: action.uri,
uris: helpers.asURIs(action.data.items),
more: action.data.next,
total: action.data.total
});
break
case 'SPOTIFY_LIBRARY_PLAYLISTS_LOADED':
var playlists = []
for( var i = 0; i < action.playlists.length; i++ ){
var playlist = Object.assign(
{},
action.playlists[i],
{
can_edit: (store.getState().spotify.authorized && store.getState().spotify.me && action.playlists[i].owner.id == store.getState().spotify.me.id),
tracks_total: action.playlists[i].tracks.total
}
)
// remove our tracklist. It'll overwrite any full records otherwise
delete playlist.tracks
playlists.push(playlist)
}
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: playlists
});
store.dispatch({
type: 'LIBRARY_PLAYLISTS_LOADED',
uris: helpers.asURIs(playlists)
});
break
case 'SPOTIFY_LIBRARY_ARTISTS_LOADED':
store.dispatch({
type: 'ARTISTS_LOADED',
@ -107,9 +193,7 @@ const SpotifyMiddleware = (function(){
break
case 'SPOTIFY_LIBRARY_ALBUMS_LOADED':
var albums = []
for (var i = 0; i < action.data.items.length; i++){
albums.push(
Object.assign(

View File

@ -144,47 +144,16 @@ export default function reducer(ui = {}, action){
case 'ALBUM_LOADED':
var albums = Object.assign([], ui.albums)
var album = Object.assign({}, action.album)
// if we already have one in our list, fetch it and update it
if (albums[action.album.uri]){
album = Object.assign({}, albums[action.album.uri], action.album)
if (albums[action.uri]){
var album = Object.assign({}, albums[action.uri], action.album)
}else{
var album = Object.assign({}, action.album)
}
albums[action.album.uri] = album
albums[action.uri] = album
return Object.assign({}, ui, { albums: albums });
case 'MOPIDY_ALBUM_LOADED':
if( !action.data ) return Object.assign({}, ui, { album: false })
return Object.assign({}, ui, { album: action.data });
case 'LASTFM_ALBUM_LOADED':
if( !action.data.image ) return ui
var album = Object.assign({}, ui.album, { images: action.data.image })
return Object.assign({}, ui, { album: album });
case 'SPOTIFY_ALBUM_LOADED':
if( !action.data ) return Object.assign({}, ui, { album: false })
var album = Object.assign({}, { images: [] }, action.data, {
tracks: action.data.tracks.items,
tracks_total: action.data.tracks.total,
tracks_more: action.data.tracks.next
})
return Object.assign({}, ui, { album: album })
case 'SPOTIFY_ALBUM_LOADED_MORE':
var album = Object.assign({}, ui.album, {
tracks: [ ...ui.album.tracks, ...action.data.items ],
tracks_more: action.data.next
})
return Object.assign({}, ui, { album: album });
case 'ALBUM_FOLLOWING_LOADED':
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, {
@ -203,6 +172,24 @@ export default function reducer(ui = {}, action){
library_albums_total: action.total
});
case 'NEW_RELEASES_LOADED':
if (!action.uris){
return Object.assign({}, ui, {
new_releases: null,
new_releases_more: null,
new_releases_total: null
});
}
var new_releases = []
if (ui.new_releases) new_releases = Object.assign([], ui.new_releases)
return Object.assign({}, ui, {
new_releases: [...new_releases, ...action.uris],
new_releases_more: action.more,
new_releases_total: action.total
});
/**
@ -224,16 +211,34 @@ export default function reducer(ui = {}, action){
case 'ARTIST_LOADED':
var artists = Object.assign([], ui.artists)
var artist = Object.assign({}, action.artist)
// if we already have one in our list, fetch it and update it
if (artists[action.artist.uri]){
artist = Object.assign({}, artists[action.artist.uri], action.artist)
if (artists[action.uri]){
var artist = Object.assign({}, artists[action.uri], action.artist)
}else{
var artist = Object.assign({}, action.artist)
}
artists[action.artist.uri] = artist
artists[action.uri] = artist
return Object.assign({}, ui, { artists: artists });
case 'ARTIST_ALBUMS_LOADED':
var artists = Object.assign([], ui.artists)
var albums_uris = []
if (artists[action.uri].albums_uris) albums_uris = artists[action.uri].albums_uris
var artist = Object.assign(
{},
artists[action.uri],
{
albums_uris: [...albums_uris, ...action.uris],
albums_more: action.more,
albums_total: action.total
}
)
artists[action.uri] = artist
return Object.assign({}, ui, { artists: artists });
/*
case 'LASTFM_ARTIST_LOADED':
if( !action.data.image ) return ui
@ -243,21 +248,7 @@ export default function reducer(ui = {}, action){
var artist = Object.assign({}, ui.artist, { images: images, bio: action.data.bio, listeners: parseInt(action.data.stats.listeners), on_tour: action.data.ontour }, )
return Object.assign({}, ui, { artist: artist });
case 'SPOTIFY_ARTIST_LOADED':
if( !action.data ) return Object.assign({}, ui, { artist: false })
return Object.assign({}, ui, { artist: action.data })
case 'SPOTIFY_ARTIST_ALBUMS_LOADED_MORE':
var artist = Object.assign({}, ui.artist, {
albums: [ ...ui.artist.albums, ...action.data.items ],
albums_more: action.data.next
})
return Object.assign({}, ui, { artist: artist });
case 'ARTIST_FOLLOWING_LOADED':
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){
@ -305,14 +296,27 @@ export default function reducer(ui = {}, action){
case 'PLAYLIST_LOADED':
case 'PLAYLIST_UPDATED':
var playlists = Object.assign([], ui.playlists)
var playlist = Object.assign({}, action.playlist)
// if we already have one in our list, fetch it and update it
if (playlists[action.playlist.uri]){
playlist = Object.assign({}, playlists[action.playlist.uri], action.playlist)
if (playlists[action.uri]){
var playlist = Object.assign({}, playlists[action.uri], action.playlist)
}else{
var playlist = Object.assign({}, action.playlist)
}
playlists[action.uri] = playlist
return Object.assign({}, ui, { playlists: playlists });
case 'PLAYLISTS_LOADED':
var playlists = Object.assign([], ui.playlists)
for (var i = 0; i < action.playlists.length; i++){
var playlist = action.playlists[i]
if (typeof(playlists[playlist.uri]) !== 'undefined'){
artist = Object.assign({}, playlists[playlist.uri], playlist)
}
playlists[playlist.uri] = playlist
}
playlists[action.playlist.uri] = playlist
return Object.assign({}, ui, { playlists: playlists });
case 'MOPIDY_PLAYLIST_LOADED':

View File

@ -25,7 +25,7 @@ class Album extends React.Component{
}
componentDidMount(){
this.loadAlbum();
this.loadAlbum()
}
componentWillReceiveProps( nextProps ){
@ -43,13 +43,14 @@ 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':
this.props.spotifyActions.getAlbum( props.params.uri );
if (props.album && props.album.tracks && props.album.artists_uris){
console.info('Loading album from index')
}else{
this.props.spotifyActions.getAlbum( props.params.uri );
}
break;
case 'local':
@ -72,9 +73,9 @@ class Album extends React.Component{
if( !this.props.album ) return null
var artists = []
if (this.props.album.artists){
for (var i = 0; i < this.props.album.artists.length; i++){
var uri = this.props.album.artists[i]
if (this.props.album.artists_uris && this.props.artists){
for (var i = 0; i < this.props.album.artists_uris.length; i++){
var uri = this.props.album.artists_uris[i]
if (this.props.artists.hasOwnProperty(uri)){
artists.push(this.props.artists[uri])
}
@ -90,7 +91,7 @@ class Album extends React.Component{
<div className="actions">
<button className="large primary" onClick={ e => this.play() }>Play</button>
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" /> : null }
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
</div>
<ul className="details">
@ -130,7 +131,7 @@ class Album extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
artists: state.ui.artists,
album: state.ui.albums[ownProps.params.uri],
album: (state.ui.albums && typeof(state.ui.albums[ownProps.params.uri]) !== 'undefined' ? state.ui.albums[ownProps.params.uri] : false ),
albums: state.ui.albums,
spotify_authorized: state.spotify.authorized,
mopidy_connected: state.mopidy.connected

View File

@ -55,11 +55,19 @@ class Artist extends React.Component{
}
loadArtist( props = this.props ){
var source = helpers.uriSource( props.params.uri );
if( source == 'spotify' ){
this.props.spotifyActions.getArtist( props.params.uri );
}else if( source == 'local' && props.mopidy_connected ){
this.props.mopidyActions.getArtist( props.params.uri );
switch( helpers.uriSource( props.params.uri ) ){
case 'spotify':
if (props.artist && props.artist.albums_uris && props.artist.related_artists_uris){
console.info('Loading spotify artist from index')
}else{
this.props.spotifyActions.getArtist( props.params.uri );
}
break
case 'local':
this.props.mopidyActions.getArtist( props.params.uri );
break
}
// go back to overview
@ -68,7 +76,7 @@ class Artist extends React.Component{
loadMore(){
if( !this.props.artist.albums_more ) return
this.props.spotifyActions.getURL( this.props.artist.albums_more, 'SPOTIFY_ARTIST_ALBUMS_LOADED_MORE' );
this.props.spotifyActions.getURL( this.props.artist.albums_more, 'SPOTIFY_ARTIST_ALBUMS_LOADED', this.props.params.uri );
}
play(){
@ -96,9 +104,9 @@ class Artist extends React.Component{
renderBody(){
var related_artists = []
if (this.props.artist.related_artists){
for (var i = 0; i < this.props.artist.related_artists.length; i++){
var uri = this.props.artist.related_artists[i]
if (this.props.artist.related_artists_uris){
for (var i = 0; i < this.props.artist.related_artists_uris.length; i++){
var uri = this.props.artist.related_artists_uris[i]
if (this.props.artists.hasOwnProperty(uri)){
related_artists.push(this.props.artists[uri])
}
@ -106,9 +114,9 @@ class Artist extends React.Component{
}
var albums = []
if (this.props.artist.albums){
for (var i = 0; i < this.props.artist.albums.length; i++){
var uri = this.props.artist.albums[i]
if (this.props.artist.albums_uris){
for (var i = 0; i < this.props.artist.albums_uris.length; i++){
var uri = this.props.artist.albums_uris[i]
if (this.props.albums.hasOwnProperty(uri)){
albums.push(this.props.albums[uri])
}
@ -191,7 +199,7 @@ class Artist extends React.Component{
<div className="actions">
<button className="large primary" onClick={ e => this.play() }>Start radio</button>
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} removeText="Unfollow" addText="Follow" /> : null }
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null }
</div>
<ul className="details">

View File

@ -110,7 +110,7 @@ class Playlist extends React.Component{
</span>
)
}
return <FollowButton uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" />
return <FollowButton uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
}
}

View File

@ -17,20 +17,31 @@ class DiscoverNewReleases extends React.Component{
}
componentDidMount(){
this.props.spotifyActions.getNewReleases();
if (!this.props.new_releases) this.props.spotifyActions.getNewReleases();
}
loadMore(){
if( !this.props.spotify.new_releases || !this.props.spotify.new_releases.next ) return
this.props.spotifyActions.getURL( this.props.spotify.new_releases.next, 'SPOTIFY_NEW_RELEASES_LOADED_MORE' );
if (!this.props.new_releases_more) return
this.props.spotifyActions.getURL(this.props.new_releases_more, 'SPOTIFY_NEW_RELEASES_LOADED');
}
render(){
var albums = []
if (this.props.new_releases){
for (var i = 0; i < this.props.new_releases.length; i++){
var uri = this.props.new_releases[i]
if (this.props.albums.hasOwnProperty(uri)){
albums.push(this.props.albums[uri])
}
}
}
return (
<div className="view discover-new-releases-view">
<Header icon="leaf" title="New Releases" />
<section className="grid-wrapper">
{ this.props.spotify.new_releases ? <AlbumGrid albums={this.props.spotify.new_releases.items} /> : null }
<AlbumGrid albums={albums} />
</section>
<LazyLoadListener loadMore={ () => this.loadMore() }/>
</div>
@ -46,7 +57,12 @@ class DiscoverNewReleases extends React.Component{
**/
const mapStateToProps = (state, ownProps) => {
return state;
return {
albums: state.ui.albums,
new_releases: state.ui.new_releases,
new_releases_more: state.ui.new_releases_more,
new_releases_total: state.ui.new_releases_total
}
}
const mapDispatchToProps = (dispatch) => {

View File

@ -85,7 +85,7 @@ class LibraryAlbums extends React.Component{
</Link>
<h4><ArtistSentence className="grey-text" artists={album.artists} /></h4>
</div>
<TrackList tracks={album.tracks.items} />
<TrackList tracks={album.tracks} />
</div>
)
})