diff --git a/src/js/services/core/actions.js b/src/js/services/core/actions.js index 42184943..a2d324cf 100755 --- a/src/js/services/core/actions.js +++ b/src/js/services/core/actions.js @@ -221,6 +221,16 @@ export function getLibraryArtists(){ * Assets loaded **/ +export function loadedMore(parent_type, parent_key, records_type, records_data){ + return { + type: 'LOADED_MORE', + parent_type: parent_type, + parent_key: parent_key, + records_type: records_type, + records_data: records_data + } +} + export function tracksLoaded(tracks){ return { type: 'TRACKS_LOADED', diff --git a/src/js/services/core/middleware.js b/src/js/services/core/middleware.js index 0efb6071..0cbfbb0f 100755 --- a/src/js/services/core/middleware.js +++ b/src/js/services/core/middleware.js @@ -220,7 +220,6 @@ const CoreMiddleware = (function(){ break; case 'MOPIDY_TLTRACKS': - var core = store.getState().core; var tracklist = [] for (var i = 0; i < action.data.length; i++){ @@ -484,19 +483,7 @@ const CoreMiddleware = (function(){ } if (playlists[playlist.uri] !== undefined){ - var existing_playlist = playlists[playlist.uri]; - - 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 (playlist.tracks){ - var tracks = playlist.tracks; - } else { - var tracks = []; - } - - playlist = Object.assign({tracks: tracks}, existing_playlist, playlist); + playlist = Object.assign({}, playlists[playlist.uri], playlist); } // Load our tracks @@ -527,7 +514,7 @@ const CoreMiddleware = (function(){ break; case 'USERS_LOADED': - var users = Object.assign([], core.users); + var users = Object.assign({}, core.users); for (var i = 0; i < action.users.length; i++){ var user = Object.assign({}, action.users[i]); @@ -548,6 +535,63 @@ const CoreMiddleware = (function(){ next(action); break; + /** + * Loaded more linked assets + * Often fired during lazy-loading or async asset grabbing. + * We link the parent to these indexed records by {type}s_uris + **/ + + case 'LOADED_MORE': + var parent_type_plural = action.parent_type+'s'; + var parent_index = Object.assign({}, core[action.parent_type+'s']); + var parent = Object.assign({}, parent_index[action.parent_key]); + + if (action.records_data.items !== undefined){ + var records = action.records_data.items; + } else if (action.records_data.tracks !== undefined){ + var records = action.records_data.tracks; + } else if (action.records_data.artists !== undefined){ + var records = action.records_data.artists; + } else if (action.records_data.albums !== undefined){ + var records = action.records_data.albums; + } else if (action.records_data.playlists !== undefined){ + var records = action.records_data.playlists; + } else { + var records = action.records_data; + } + + if (action.records_type == 'track'){ + records = helpers.formatTracks(records); + } + + var records_type_plural = action.records_type+'s'; + var records_index = Object.assign({}); + var records_uris = helpers.arrayOf('uri', records); + + // Append our records_uris array with our new records + var uris = [...parent[records_type_plural+'_uris'], ...records_uris]; + parent[records_type_plural+'_uris'] = uris; + if (action.records_data.next !== undefined){ + parent[records_type_plural+'_more'] = action.records_data.next; + } + + // Parent loaded (well, changed) + var parent_action = { + type: parent_type_plural.toUpperCase()+'_LOADED' + }; + parent_action[parent_type_plural] = [parent]; + store.dispatch(parent_action); + + // Records loaded + var records_action = { + type: records_type_plural.toUpperCase()+'_LOADED' + }; + records_action[records_type_plural] = records; + store.dispatch(records_action); + + 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/spotify/actions.js b/src/js/services/spotify/actions.js index 791578f2..f88c6e21 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -505,6 +505,40 @@ export function getURL(url, action_name, key = false){ } } +export function loadMore(url, loaded_more_action = null, custom_action = null){ + return (dispatch, getState) => { + sendRequest(dispatch, getState, url) + .then( + response => { + if (loaded_more_action){ + dispatch(coreActions.loadedMore( + loaded_more_action.parent_type, + loaded_more_action.parent_key, + loaded_more_action.records_type, + response + )); + } else if (custom_action){ + dispatch({ + type: custom_action.type, + key: custom_action.key, + data: response + }); + } else { + dispatch(coreActions.handleException( + 'No callback handler for loading more items' + )); + } + }, + error => { + dispatch(coreActions.handleException( + 'Could not load more '+callback_action.parent_type+' '+callback_action.records_type+'s', + error + )); + } + ); + } +} + export function clearSearchResults(){ return { type: 'SPOTIFY_CLEAR_SEARCH_RESULTS' diff --git a/src/js/views/Album.js b/src/js/views/Album.js index f24df0b0..745dddfc 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -85,7 +85,14 @@ class Album extends React.Component{ } loadMore(){ - this.props.spotifyActions.getURL(this.props.album.tracks_more, 'SPOTIFY_ALBUM_LOADED_MORE' ); + this.props.spotifyActions.loadMore( + this.props.album.tracks_more, + { + parent_type: 'album', + parent_key: this.props.album.uri, + records_type: 'track' + } + ); } play(){ diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index 28517d2b..026ac9fb 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -74,7 +74,14 @@ class Playlist extends React.Component{ } loadMore(){ - this.props.spotifyActions.getURL(this.props.playlist.tracks_more, 'PLAYLIST_LOADED_MORE_TRACKS', this.props.playlist.uri ); + this.props.spotifyActions.loadMore( + this.props.playlist.tracks_more, + { + parent_type: 'playlist', + parent_key: this.props.playlist.uri, + records_type: 'track' + } + ); } play(){ @@ -223,7 +230,7 @@ const mapStateToProps = (state, ownProps) => { slim_mode: state.ui.slim_mode, load_queue: state.ui.load_queue, tracks: state.core.tracks, - playlist: (state.core.playlists && state.core.playlists[uri] !== undefined ? state.core.playlists[uri] : false ), + playlist: (state.core.playlists[uri] !== undefined ? state.core.playlists[uri] : false ), spotify_library_playlists: state.spotify.library_playlists, local_library_playlists: state.mopidy.library_playlists, mopidy_connected: state.mopidy.connected, diff --git a/src/js/views/discover/DiscoverCategory.js b/src/js/views/discover/DiscoverCategory.js index 67a44e05..480e53f7 100755 --- a/src/js/views/discover/DiscoverCategory.js +++ b/src/js/views/discover/DiscoverCategory.js @@ -30,7 +30,14 @@ class DiscoverCategory extends React.Component{ } loadMore(){ - this.props.spotifyActions.getURL(this.props.category.playlists_more, 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED', 'category:'+this.props.params.id ); + this.props.spotifyActions.loadMore( + this.props.category.playlists_more, + null, + { + type: 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED', + key: 'category:'+this.props.params.id + } + ); } render(){ diff --git a/src/js/views/discover/DiscoverNewReleases.js b/src/js/views/discover/DiscoverNewReleases.js index 866f275e..831d59e4 100755 --- a/src/js/views/discover/DiscoverNewReleases.js +++ b/src/js/views/discover/DiscoverNewReleases.js @@ -27,7 +27,14 @@ class DiscoverNewReleases extends React.Component{ } loadMore(){ - this.props.spotifyActions.getURL(this.props.new_releases_more, 'SPOTIFY_NEW_RELEASES_LOADED'); + this.props.spotifyActions.loadMore( + this.props.new_releases_more, + null, + { + type: 'SPOTIFY_NEW_RELEASES_LOADED', + key: null + } + ); } playAlbum(e,album){