Unifying loading and index updating

This commit is contained in:
James Barnsley
2018-08-12 20:59:00 +12:00
parent f235a1c48c
commit e1fad661e5
8 changed files with 552 additions and 413 deletions

View File

@ -78,6 +78,115 @@ export function cachebustHttpStream(){
}
}
/**
* Record getters
*
* Calling this through the common core enables us to detect whether we've already
* got the record in the state or persistent storage. Failing that, we pass off to the
* relevant service to load the record - all from one neat package.
**/
export function loadTrack(uri){
return {
type: 'LOAD_TRACK',
uri: uri
}
}
export function loadAlbum(uri){
return {
type: 'LOAD_ALBUM',
uri: uri
}
}
export function loadArtist(uri){
return {
type: 'LOAD_ARTIST',
uri: uri
}
}
export function loadPlaylist(uri){
return {
type: 'LOAD_PLAYLIST',
uri: uri
}
}
export function loadUser(uri){
return {
type: 'LOAD_USER',
uri: uri
}
}
/**
* Record loaders
*
* We've got a loaded record, now we just need to plug it in to our state and stores.
**/
export function trackLoaded(track){
return tracksLoaded([track]);
}
export function tracksLoaded(tracks){
return {
type: 'TRACKS_LOADED',
tracks: tracks
}
}
export function artistLoaded(artist){
return artistsLoaded([artist]);
}
export function artistsLoaded(artists){
return {
type: 'ARTISTS_LOADED',
artists: artists
}
}
export function albumLoaded(album){
return albumsLoaded([album]);
}
export function albumsLoaded(albums){
return {
type: 'ALBUMS_LOADED',
albums: albums
}
}
export function playlistLoaded(playlist){
return playlistsLoaded([playlist]);
}
export function playlistsLoaded(playlists){
return {
type: 'PLAYLISTS_LOADED',
playlists: playlists
}
}
export function userLoaded(user){
return usersLoaded([user]);
}
export function usersLoaded(users){
return {
type: 'USERS_LOADED',
users: users
}
}
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
}
}
@ -221,53 +330,3 @@ export function getLibraryArtists(){
type: 'GET_LIBRARY_ARTISTS'
}
}
/**
* 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',
tracks: tracks
}
}
export function albumsLoaded(albums){
return {
type: 'ALBUMS_LOADED',
albums: albums
}
}
export function artistsLoaded(artists){
return {
type: 'ARTISTS_LOADED',
artists: artists
}
}
export function playlistsLoaded(playlists){
return {
type: 'PLAYLISTS_LOADED',
playlists: playlists
}
}
export function usersLoaded(users){
return {
type: 'USERS_LOADED',
users: users
}
}

View File

@ -356,59 +356,81 @@ const CoreMiddleware = (function(){
break;
case 'LOAD_TRACK':
switch (helpers.uriSource(action.uri)){
case 'spotify':
store.dispatch(spotifyActions.getTrack(action.uri));
//store.dispatch(spotifyActions.following(action.uri));
break;
default:
store.dispatch(mopidyActions.getTrack(action.uri));
break;
}
next(action);
break;
case 'LOAD_ALBUM':
switch (helpers.uriSource(action.uri)){
case 'spotify':
store.dispatch(spotifyActions.getAlbum(action.uri));
store.dispatch(spotifyActions.following(action.uri));
break;
default:
store.dispatch(mopidyActions.getAlbum(action.uri));
break;
}
next(action);
break;
case 'LOAD_ARTIST':
switch (helpers.uriSource(action.uri)){
case 'spotify':
store.dispatch(spotifyActions.getArtist(action.uri, true));
store.dispatch(spotifyActions.following(action.uri));
break;
default:
store.dispatch(mopidyActions.getArtist(action.uri));
break;
}
next(action);
break;
case 'LOAD_PLAYLIST':
switch (helpers.uriSource(action.uri)){
case 'spotify':
store.dispatch(spotifyActions.getPlaylist(action.uri));
store.dispatch(spotifyActions.following(action.uri));
break;
default:
store.dispatch(mopidyActions.getPlaylist(action.uri));
break;
}
next(action);
break;
/**
* Index actions
* These modify our asset indexes, which are used globally
**/
// Array wrapper for TRACKS_LOADED
case 'TRACK_LOADED':
store.dispatch({
type: 'TRACKS_LOADED',
tracks: [action.track]
});
break;
// Array wrapper for ALBUMS_LOADED
case 'ALBUM_LOADED':
store.dispatch({
type: 'ALBUMS_LOADED',
albums: [action.album]
});
break;
// Array wrapper for ARTISTS_LOADED
case 'ARTIST_LOADED':
store.dispatch({
type: 'ARTISTS_LOADED',
artists: [action.artist]
});
break;
// Array wrapper for PLAYLISTS_LOADED
case 'PLAYLIST_LOADED':
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: [action.playlist]
});
break;
// Array wrapper for USERS_LOADED
case 'USER_LOADED':
store.dispatch({
type: 'USERS_LOADED',
users: [action.user]
});
break;
case 'TRACKS_LOADED':
var tracks = Object.assign({}, core.tracks);
var tracks_index = Object.assign({}, core.tracks);
var tracks_loaded = [];
for (var i = 0; i < action.tracks.length; i++){
var track = Object.assign({}, helpers.formatTracks(action.tracks[i]));
action.tracks.forEach(track => {
track = helpers.formatTracks(track);
if (tracks[track.uri] !== undefined){
track = Object.assign({}, tracks[track.uri], track);
if (tracks_index[track.uri] !== undefined){
track = Object.assign({}, tracks_index[track.uri], track);
}
if (track.album && track.album.images && track.album.images.length > 0){
@ -416,28 +438,24 @@ const CoreMiddleware = (function(){
track.images = track.album.images;
}
tracks[track.uri] = track;
}
// Update index
store.dispatch({
type: 'UPDATE_TRACKS_INDEX',
tracks: tracks
tracks_loaded.push(track);
});
action.tracks = tracks_loaded;
next(action);
break;
case 'ALBUMS_LOADED':
var albums = Object.assign({}, core.albums);
var albums_index = Object.assign({}, core.albums);
var albums_loaded = [];
var tracks_loaded = [];
for (var i = 0; i < action.albums.length; i++){
var album = Object.assign({}, action.albums[i]);
action.albums.forEach(album => {
helpers.formatAlbum(album)
if (albums[album.uri]){
album = Object.assign({}, albums[album.uri], album);
if (albums_index[album.uri]){
album = Object.assign({}, albums_index[album.uri], album);
}
if (album.images && album.images.length > 0){
@ -453,43 +471,39 @@ const CoreMiddleware = (function(){
tracks_loaded = [...tracks_loaded, ...tracks];
}
albums[album.uri] = album;
}
albums_loaded.push(album);
});
// Load these new tracks
action.albums = albums_loaded;
// Trigger the tracks load action
store.dispatch({
type: 'TRACKS_LOADED',
tracks: tracks_loaded
});
// Update index
store.dispatch({
type: 'UPDATE_ALBUMS_INDEX',
albums: albums
});
next(action);
break
case 'ARTISTS_LOADED':
var artists = Object.assign({}, core.artists);
var artists_index = Object.assign({}, core.artists);
var artists_loaded = [];
var tracks_loaded = [];
for (var i = 0; i < action.artists.length; i++){
var artist = action.artists[i];
if (artists[artist.uri]){
action.artists.forEach(artist => {
if (artists_index[artist.uri]){
// if we've already got images, remove and add as additional_images
// this is to prevent LastFM overwriting Spotify images
if (artists[artist.uri].images){
if (artists_index[artist.uri].images){
artist.images_additional = artist.images
delete artist.images
}
artist = Object.assign({}, artists[artist.uri], artist);
artist = Object.assign({}, artists_index[artist.uri], artist);
}
// Migrate nested tracks objects into references to our tracks index
if (artist.tracks){
var tracks = helpers.formatTracks(artist.tracks);
var tracks_uris = helpers.arrayOf('uri', tracks);
@ -498,30 +512,22 @@ const CoreMiddleware = (function(){
tracks_loaded = [...tracks_loaded, ...tracks];
}
// Update index
artists[artist.uri] = artist;
}
// Load our tracks
store.dispatch({
type: 'TRACKS_LOADED',
tracks: tracks_loaded
artists_loaded.push(artist);
});
store.dispatch({
type: 'UPDATE_ARTISTS_INDEX',
artists: artists
});
action.artists = artists_loaded;
store.dispatch(coreActions.tracksLoaded(tracks_loaded));
next(action);
break;
case 'PLAYLISTS_LOADED':
var playlists = Object.assign({}, core.playlists);
var playlists_index = Object.assign({}, core.playlists);
var playlists_loaded = [];
var tracks_loaded = [];
for (var i = 0; i < action.playlists.length; i++){
var playlist = Object.assign({}, action.playlists[i]);
action.playlists.forEach(playlist => {
// Detect editability
switch (helpers.uriSource(playlist.uri)){
@ -536,8 +542,8 @@ const CoreMiddleware = (function(){
}
}
if (playlists[playlist.uri] !== undefined){
playlist = Object.assign({}, playlists[playlist.uri], playlist);
if (playlists_index[playlist.uri]){
playlist = Object.assign({}, playlists_index[playlist.uri], playlist);
}
// Load our tracks
@ -550,42 +556,32 @@ const CoreMiddleware = (function(){
}
// Update index
playlists[playlist.uri] = playlist;
}
playlists_loaded.push(playlist);
});
action.playlists = playlists_loaded;
// Load our tracks
store.dispatch({
type: 'TRACKS_LOADED',
tracks: tracks_loaded
});
store.dispatch({
type: 'UPDATE_PLAYLISTS_INDEX',
playlists: playlists
});
store.dispatch(coreActions.tracksLoaded(tracks_loaded));
next(action);
break;
case 'USERS_LOADED':
var users = Object.assign({}, core.users);
var users_index = Object.assign({}, core.users);
var users_loaded = [];
for (var i = 0; i < action.users.length; i++){
var user = Object.assign({}, action.users[i]);
action.users.forEach(user => {
if (users[user.uri]){
user = Object.assign({}, users[user.uri], user);
if (users_index[user.uri]){
user = Object.assign({}, users_index[user.uri], user);
}
users[user.uri] = user;
}
// Update index
store.dispatch({
type: 'UPDATE_USERS_INDEX',
users: users
users_loaded.push(user);
});
action.users = users_loaded;
next(action);
break;

View File

@ -122,21 +122,40 @@ export default function reducer(core = {}, action){
* and appended to their relevant index.
**/
case 'UPDATE_TRACKS_INDEX':
return Object.assign({}, core, { tracks: action.tracks });
case 'TRACKS_LOADED':
var tracks = Object.assign({}, core.tracks);
action.tracks.forEach(track => {
tracks[track.uri] = track;
});
return Object.assign({}, core, { tracks: tracks });
case 'UPDATE_ALBUMS_INDEX':
return Object.assign({}, core, { albums: action.albums });
case 'ALBUMS_LOADED':
var albums = Object.assign({}, core.albums);
action.albums.forEach(album => {
albums[album.uri] = album;
});
return Object.assign({}, core, { albums: albums });
case 'UPDATE_ARTISTS_INDEX':
return Object.assign({}, core, { artists: action.artists });
case 'ARTISTS_LOADED':
var artists = Object.assign({}, core.artists);
action.artists.forEach(artist => {
artists[artist.uri] = artist;
});
return Object.assign({}, core, { artists: artists });
case 'UPDATE_PLAYLISTS_INDEX':
return Object.assign({}, core, { playlists: action.playlists });
case 'UPDATE_USERS_INDEX':
return Object.assign({}, core, { users: action.users });
case 'PLAYLISTS_LOADED':
var playlists = Object.assign({}, core.playlists);
action.playlists.forEach(playlist => {
playlists[playlist.uri] = playlist;
});
return Object.assign({}, core, { playlists: playlists });
case 'USERS_LOADED':
var users = Object.assign({}, core.users);
action.users.forEach(user => {
users[user.uri] = user;
});
return Object.assign({}, core, { users: users });
case 'NEW_RELEASES_LOADED':
@ -159,25 +178,27 @@ export default function reducer(core = {}, action){
case 'ARTIST_ALBUMS_LOADED':
var artists = Object.assign([], core.artists)
var albums_uris = []
if (artists[action.key].albums_uris) albums_uris = artists[action.key].albums_uris
var artists = Object.assign({}, core.artists)
var albums_uris = [];
if (artists[action.artist_uri].albums_uris){
albums_uris = artists[action.artist_uri].albums_uris;
}
var artist = Object.assign(
{},
artists[action.key],
artists[action.artist_uri],
{
albums_uris: [...albums_uris, ...action.uris],
albums_uris: [...albums_uris, ...action.albums_uris],
albums_more: action.more,
albums_total: action.total
}
)
artists[action.key] = artist
artists[action.artist_uri] = artist
return Object.assign({}, core, { artists: artists });
case 'USER_PLAYLISTS_LOADED':
var users = Object.assign([], core.users)
var users = Object.assign({}, core.users)
var playlists_uris = []
if (users[action.key] && users[action.key].playlists_uris) playlists_uris = users[action.key].playlists_uris
@ -201,7 +222,7 @@ export default function reducer(core = {}, action){
**/
case 'PLAYLIST_TRACKS':
var playlists = Object.assign([], core.playlists)
var playlists = Object.assign({}, core.playlists)
var playlist = Object.assign({}, playlists[action.key], { tracks_uris: action.tracks_uris })
playlists[action.key] = playlist

View File

@ -1120,10 +1120,7 @@ export function getArtist(uri, full = false){
sendRequest(dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' )
.then(
response => {
dispatch({
type: 'ARTISTS_LOADED',
artists: response.artists
});
dispatch(coreActions.artistsLoaded(response.artists));
Object.assign(artist, { related_artists_uris: helpers.arrayOf('uri',response.artists) });
},
error => {
@ -1145,11 +1142,7 @@ export function getArtist(uri, full = false){
dispatch(lastfmActions.getArtist(artist.uri, artist.name.replace('&','and')))
}
dispatch({
type: 'ARTIST_LOADED',
key: artist.uri,
artist: artist
})
dispatch(coreActions.artistLoaded(artist));
// Now go get our artist albums
if (full){
@ -1158,8 +1151,8 @@ export function getArtist(uri, full = false){
response => {
dispatch({
type: 'SPOTIFY_ARTIST_ALBUMS_LOADED',
data: response,
key: uri
artist_uri: uri,
data: response
})
},
error => {
@ -1578,11 +1571,7 @@ export function getPlaylist(uri){
}
)
dispatch({
type: 'PLAYLIST_LOADED',
key: playlist.uri,
playlist: playlist
})
dispatch(coreActions.playlistLoaded(playlist));
},
error => {
dispatch(coreActions.handleException(

View File

@ -3,6 +3,7 @@ import ReactGA from 'react-ga';
import md5 from 'md5';
var helpers = require('./../../helpers');
var coreActions = require('../core/actions');
var spotifyActions = require('./actions');
var uiActions = require('../ui/actions');
var pusherActions = require('../pusher/actions');
@ -114,14 +115,12 @@ const SpotifyMiddleware = (function(){
break
case 'SPOTIFY_ARTIST_ALBUMS_LOADED':
store.dispatch({
type: 'ALBUMS_LOADED',
albums: action.data.items
});
console.log(action)
store.dispatch(coreActions.albumsLoaded(action.data.items));
store.dispatch({
type: 'ARTIST_ALBUMS_LOADED',
key: action.key,
uris: helpers.arrayOf('uri',action.data.items),
artist_uri: action.artist_uri,
albums_uris: helpers.arrayOf('uri',action.data.items),
more: action.data.next,
total: action.data.total
});