Playlist and Users data storage overhaul
This commit is contained in:
@ -86,38 +86,51 @@ export function cachebustHttpStream(){
|
||||
* relevant service to load the record - all from one neat package.
|
||||
**/
|
||||
|
||||
export function loadTrack(uri){
|
||||
export function loadTrack(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_TRACK',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
export function loadAlbum(uri){
|
||||
export function loadAlbum(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_ALBUM',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
export function loadArtist(uri){
|
||||
export function loadArtist(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_ARTIST',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
export function loadPlaylist(uri){
|
||||
export function loadPlaylist(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_PLAYLIST',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
export function loadUser(uri){
|
||||
export function loadUser(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_USER',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
export function loadUserPlaylists(uri, force_reload = false){
|
||||
return {
|
||||
type: 'LOAD_USER_PLAYLISTS',
|
||||
uri: uri,
|
||||
force_reload: force_reload
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +190,15 @@ export function usersLoaded(users){
|
||||
users: users
|
||||
}
|
||||
}
|
||||
export function userPlaylistsLoaded(uri, playlists, more = null, total = null){
|
||||
return {
|
||||
type: 'USER_PLAYLISTS_LOADED',
|
||||
uri: uri,
|
||||
playlists: playlists,
|
||||
more: more,
|
||||
total: total
|
||||
}
|
||||
}
|
||||
|
||||
export function loadedMore(parent_type, parent_key, records_type, records_data){
|
||||
return {
|
||||
|
||||
@ -357,6 +357,14 @@ const CoreMiddleware = (function(){
|
||||
|
||||
|
||||
case 'LOAD_TRACK':
|
||||
|
||||
if (
|
||||
!action.force_reload &&
|
||||
store.getState().core.tracks[action.uri]){
|
||||
console.info('Loading "'+action.uri+'" from index');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getTrack(action.uri));
|
||||
@ -374,6 +382,15 @@ const CoreMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'LOAD_ALBUM':
|
||||
|
||||
if (
|
||||
!action.force_reload &&
|
||||
store.getState().core.albums[action.uri] &&
|
||||
store.getState().core.albums[action.uri].tracks_uris){
|
||||
console.info('Loading "'+action.uri+'" from index');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getAlbum(action.uri));
|
||||
@ -391,6 +408,16 @@ const CoreMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'LOAD_ARTIST':
|
||||
|
||||
if (
|
||||
!action.force_reload &&
|
||||
store.getState().core.artists[action.uri] &&
|
||||
store.getState().core.artists[action.uri].albums_uris &&
|
||||
store.getState().core.artists[action.uri].tracks_uris){
|
||||
console.info('Loading "'+action.uri+'" from index');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getArtist(action.uri, true));
|
||||
@ -408,6 +435,15 @@ const CoreMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'LOAD_PLAYLIST':
|
||||
|
||||
if (
|
||||
!action.force_reload &&
|
||||
store.getState().core.playlists[action.uri] &&
|
||||
store.getState().core.playlists[action.uri].tracks_uris){
|
||||
console.info('Loading "'+action.uri+'" from index');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getPlaylist(action.uri));
|
||||
@ -424,6 +460,46 @@ const CoreMiddleware = (function(){
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'LOAD_USER':
|
||||
|
||||
console.log(action);
|
||||
|
||||
if (
|
||||
!action.force_reload &&
|
||||
store.getState().core.playlists[action.uri] &&
|
||||
store.getState().core.playlists[action.uri].albums_uris ){
|
||||
console.info('Loading "'+action.uri+'" from index');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getUser(action.uri));
|
||||
store.dispatch(spotifyActions.following(action.uri));
|
||||
break;
|
||||
|
||||
default:
|
||||
// No Mopidy mechanism for users
|
||||
break;
|
||||
}
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'LOAD_USER_PLAYLISTS':
|
||||
switch (helpers.uriSource(action.uri)){
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getUserPlaylists(action.uri));
|
||||
break;
|
||||
|
||||
default:
|
||||
// No Mopidy mechanism for users
|
||||
break;
|
||||
}
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* Index actions
|
||||
@ -537,7 +613,9 @@ const CoreMiddleware = (function(){
|
||||
var playlists_loaded = [];
|
||||
var tracks_loaded = [];
|
||||
|
||||
action.playlists.forEach(playlist => {
|
||||
for (var playlist of action.playlists){
|
||||
|
||||
playlist = helpers.formatPlaylist(playlist);
|
||||
|
||||
// Detect editability
|
||||
switch (helpers.uriSource(playlist.uri)){
|
||||
@ -567,7 +645,7 @@ const CoreMiddleware = (function(){
|
||||
|
||||
// Update index
|
||||
playlists_loaded.push(playlist);
|
||||
});
|
||||
}
|
||||
|
||||
action.playlists = playlists_loaded;
|
||||
|
||||
@ -581,20 +659,25 @@ const CoreMiddleware = (function(){
|
||||
var users_index = Object.assign({}, core.users);
|
||||
var users_loaded = [];
|
||||
|
||||
action.users.forEach(user => {
|
||||
for (var user of action.users){
|
||||
|
||||
if (users_index[user.uri]){
|
||||
user = Object.assign({}, users_index[user.uri], user);
|
||||
}
|
||||
|
||||
users_loaded.push(user);
|
||||
});
|
||||
}
|
||||
|
||||
action.users = users_loaded;
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'USER_PLAYLISTS_LOADED':
|
||||
store.dispatch(coreActions.playlistsLoaded(action.playlists));
|
||||
next(action);
|
||||
break;
|
||||
|
||||
/**
|
||||
* Loaded more linked assets
|
||||
* Often fired during lazy-loading or async asset grabbing.
|
||||
|
||||
@ -124,37 +124,37 @@ export default function reducer(core = {}, action){
|
||||
|
||||
case 'TRACKS_LOADED':
|
||||
var tracks = Object.assign({}, core.tracks);
|
||||
action.tracks.forEach(track => {
|
||||
for (var track of action.tracks){
|
||||
tracks[track.uri] = track;
|
||||
});
|
||||
}
|
||||
return Object.assign({}, core, { tracks: tracks });
|
||||
|
||||
case 'ALBUMS_LOADED':
|
||||
var albums = Object.assign({}, core.albums);
|
||||
action.albums.forEach(album => {
|
||||
for (var album of action.albums){
|
||||
albums[album.uri] = album;
|
||||
});
|
||||
}
|
||||
return Object.assign({}, core, { albums: albums });
|
||||
|
||||
case 'ARTISTS_LOADED':
|
||||
var artists = Object.assign({}, core.artists);
|
||||
action.artists.forEach(artist => {
|
||||
for (var artist of action.artists){
|
||||
artists[artist.uri] = artist;
|
||||
});
|
||||
}
|
||||
return Object.assign({}, core, { artists: artists });
|
||||
|
||||
case 'PLAYLISTS_LOADED':
|
||||
var playlists = Object.assign({}, core.playlists);
|
||||
action.playlists.forEach(playlist => {
|
||||
for (var playlist of action.playlists){
|
||||
playlists[playlist.uri] = playlist;
|
||||
});
|
||||
}
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'USERS_LOADED':
|
||||
var users = Object.assign({}, core.users);
|
||||
action.users.forEach(user => {
|
||||
for (var user of action.users){
|
||||
users[user.uri] = user;
|
||||
});
|
||||
}
|
||||
return Object.assign({}, core, { users: users });
|
||||
|
||||
|
||||
@ -167,8 +167,10 @@ export default function reducer(core = {}, action){
|
||||
});
|
||||
}
|
||||
|
||||
var new_releases = []
|
||||
if (core.new_releases) new_releases = Object.assign([], core.new_releases)
|
||||
var new_releases = [];
|
||||
if (core.new_releases){
|
||||
new_releases = Object.assign([], core.new_releases);
|
||||
}
|
||||
|
||||
return Object.assign({}, core, {
|
||||
new_releases: [...new_releases, ...action.uris],
|
||||
@ -199,19 +201,23 @@ export default function reducer(core = {}, action){
|
||||
|
||||
case 'USER_PLAYLISTS_LOADED':
|
||||
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
|
||||
var existing_playlists_uris = [];
|
||||
if (users[action.uri] && users[action.uri].playlists_uris){
|
||||
existing_playlists_uris = users[action.uri].playlists_uris;
|
||||
}
|
||||
|
||||
var artist = Object.assign(
|
||||
var playlists_uris = [...existing_playlists_uris, ...helpers.arrayOf('uri',action.playlists)]
|
||||
|
||||
var user = Object.assign(
|
||||
{},
|
||||
users[action.key],
|
||||
users[action.uri],
|
||||
{
|
||||
playlists_uris: [...playlists_uris, ...action.uris],
|
||||
playlists_uris: playlists_uris,
|
||||
playlists_more: action.more,
|
||||
playlists_total: action.total
|
||||
}
|
||||
)
|
||||
users[action.key] = artist
|
||||
users[action.uri] = user;
|
||||
return Object.assign({}, core, { users: users });
|
||||
|
||||
|
||||
|
||||
@ -239,10 +239,10 @@ export function getArtist(uri, artist, mbid = false){
|
||||
uri: uri,
|
||||
images: response.artist.image,
|
||||
mbid: response.artist.mbid,
|
||||
bio: response.artist.bio,
|
||||
listeners: parseInt(response.artist.stats.listeners),
|
||||
play_count: parseInt(response.artist.stats.playcount),
|
||||
on_tour: response.artist.stats.ontour
|
||||
biography: response.artist.bio.content,
|
||||
biography_publish_date: response.artist.bio.published,
|
||||
biography_link: response.artist.bio.links.link.href,
|
||||
listeners: parseInt(response.artist.stats.listeners)
|
||||
};
|
||||
|
||||
dispatch(coreActions.artistLoaded(artist));
|
||||
|
||||
@ -1750,26 +1750,43 @@ const MopidyMiddleware = (function(){
|
||||
.then(response => {
|
||||
if (response.length <= 0) return
|
||||
|
||||
var albums = []
|
||||
var albums_loaded = [];
|
||||
var artists_loaded = [];
|
||||
var tracks_loaded = [];
|
||||
|
||||
for (var uri in response){
|
||||
if (response.hasOwnProperty(uri) && response[uri].length > 0 && response[uri][0] && response[uri][0].album){
|
||||
|
||||
var artists_uris = [];
|
||||
for (var artist in response[uri][0].artists){
|
||||
artists_loaded.push(helpers.formatArtist(artist));
|
||||
artists_uris.push(artist.uri);
|
||||
}
|
||||
|
||||
var tracks_uris = [];
|
||||
for (var track in response[uri]){
|
||||
tracks_loaded.push(helpers.formatTrack(track));
|
||||
tracks_uris.push(track.uri);
|
||||
}
|
||||
|
||||
var album = Object.assign(
|
||||
{},
|
||||
{
|
||||
source: 'local',
|
||||
artists: response[uri][0].artists,
|
||||
tracks: response[uri],
|
||||
tracks_total: response[uri].length
|
||||
artists_uris: artists_uris,
|
||||
tracks_uris: tracks_uris,
|
||||
tracks_total: tracks_uris.length
|
||||
},
|
||||
response[uri][0].album
|
||||
)
|
||||
|
||||
albums.push(album)
|
||||
albums_loaded.push(album);
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatch(coreActions.albumsLoaded(albums));
|
||||
store.dispatch(coreActions.albumsLoaded(albums_loaded));
|
||||
store.dispatch(coreActions.artistsLoaded(artists_loaded));
|
||||
store.dispatch(coreActions.tracksLoaded(tracks_loaded));
|
||||
|
||||
// Re-run any consequential processes in 100ms. This allows a small window for other
|
||||
// server requests before our next batch. It's a little crude but it means the server isn't
|
||||
@ -1788,26 +1805,31 @@ const MopidyMiddleware = (function(){
|
||||
case 'MOPIDY_GET_ALBUM':
|
||||
request(socket, store, 'library.lookup', action.data)
|
||||
.then(response => {
|
||||
if (response.length <= 0){
|
||||
if (!response || response.length <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
var artists = [];
|
||||
for (var artist of response[0].artists){
|
||||
artists.push(helpers.formatArtist(artist));
|
||||
}
|
||||
|
||||
var album = Object.assign(
|
||||
{},
|
||||
{ images: [] },
|
||||
response[0].album,
|
||||
{
|
||||
images: []
|
||||
},
|
||||
helpers.formatAlbum(response[0].album),
|
||||
{
|
||||
source: 'local',
|
||||
artists: response[0].artists,
|
||||
tracks: response,
|
||||
artists_uris: helpers.arrayOf('uri', artists),
|
||||
tracks_uris: helpers.arrayOf('uri', response),
|
||||
tracks_total: response.length
|
||||
}
|
||||
)
|
||||
|
||||
var uris = [];
|
||||
for(var i = 0; i < album.tracks.length; i++){
|
||||
uris.push(album.tracks[i].uri );
|
||||
}
|
||||
);
|
||||
|
||||
store.dispatch(coreActions.albumLoaded(album));
|
||||
store.dispatch(coreActions.artistsLoaded(artists));
|
||||
|
||||
// load artwork from LastFM
|
||||
if (album.images.length <= 0){
|
||||
@ -1819,29 +1841,17 @@ const MopidyMiddleware = (function(){
|
||||
}
|
||||
}
|
||||
|
||||
request(socket, store, 'library.lookup', { uris: uris } )
|
||||
request(socket, store, 'library.lookup', { uris: album.tracks_uris } )
|
||||
.then(response => {
|
||||
var tracks_loaded = [];
|
||||
|
||||
for(var uri in response){
|
||||
for (var uri in response){
|
||||
if (response.hasOwnProperty(uri)){
|
||||
|
||||
var track = response[uri][0];
|
||||
|
||||
// find the track reference, and drop in the full track data
|
||||
function getByURI(trackReference){
|
||||
return track.uri == trackReference.uri
|
||||
}
|
||||
var trackReferences = album.tracks.filter(getByURI);
|
||||
|
||||
// there could be multiple instances of this track, so accommodate this
|
||||
for(var j = 0; j < trackReferences.length; j++){
|
||||
var key = album.tracks.indexOf(trackReferences[j] );
|
||||
album.tracks[ key ] = track;
|
||||
}
|
||||
tracks_loaded.push(response[uri][0]);
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatch(coreActions.albumLoaded(album));
|
||||
store.dispatch(coreActions.tracksLoaded(tracks_loaded));
|
||||
})
|
||||
})
|
||||
break;
|
||||
|
||||
@ -1229,17 +1229,12 @@ export function playArtistTopTracks(uri){
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
export function getUser(uri, and_playlists = false){
|
||||
export function getUser(uri){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// get the user
|
||||
sendRequest(dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) )
|
||||
sendRequest(dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri))
|
||||
.then(
|
||||
response => {
|
||||
dispatch({
|
||||
type: 'USERS_LOADED',
|
||||
users: [response]
|
||||
});
|
||||
dispatch(coreActions.userLoaded(helpers.formatUser(response)));
|
||||
},
|
||||
error => {
|
||||
dispatch(coreActions.handleException(
|
||||
@ -1247,46 +1242,38 @@ export function getUser(uri, and_playlists = false){
|
||||
error
|
||||
));
|
||||
}
|
||||
)
|
||||
|
||||
if (and_playlists){
|
||||
dispatch(getUserPlaylists(uri));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function getUserPlaylists(user_uri){
|
||||
export function getUserPlaylists(uri){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// get the first page of playlists
|
||||
sendRequest(dispatch, getState, 'users/'+ helpers.getFromUri('userid', user_uri) +'/playlists?limit=40' )
|
||||
sendRequest(dispatch, getState, 'users/'+ helpers.getFromUri('userid', uri) +'/playlists?limit=40' )
|
||||
.then(
|
||||
response => {
|
||||
var playlists = []
|
||||
for (var i = 0; i < response.items.length; i++){
|
||||
var playlists = [];
|
||||
for (var raw_playlist of response.items){
|
||||
|
||||
var can_edit = false
|
||||
if (getState().spotify.me && response.items[i].owner.id == getState().spotify.me.id){
|
||||
can_edit = true
|
||||
var can_edit = false;
|
||||
if (getState().spotify.me && raw_playlist.owner.id == getState().spotify.me.id){
|
||||
can_edit = true;
|
||||
}
|
||||
|
||||
playlists.push(Object.assign(
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
response.items[i],
|
||||
helpers.formatPlaylist(raw_playlist),
|
||||
{
|
||||
can_edit: can_edit,
|
||||
tracks_total: response.items[i].tracks.total
|
||||
tracks_total: raw_playlist.tracks.total
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
playlists.push(playlist);
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'LOADED_MORE',
|
||||
parent_type: 'user',
|
||||
parent_key: user_uri,
|
||||
records_type: 'playlist',
|
||||
records_data: response
|
||||
});
|
||||
dispatch(coreActions.userPlaylistsLoaded(uri, playlists, response.more, response.total));
|
||||
},
|
||||
error => {
|
||||
dispatch(coreActions.handleException(
|
||||
@ -1322,26 +1309,29 @@ export function getAlbum(uri){
|
||||
// dispatch our loaded artists (simple objects)
|
||||
dispatch(coreActions.artistsLoaded(response.artists));
|
||||
|
||||
var tracks = Object.assign([], response.tracks.items);
|
||||
|
||||
var album = Object.assign(
|
||||
{},
|
||||
response,
|
||||
helpers.formatAlbum(response),
|
||||
{
|
||||
artists_uris: helpers.arrayOf('uri',response.artists),
|
||||
tracks: response.tracks.items,
|
||||
tracks_uris: helpers.arrayOf('uri', tracks),
|
||||
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 = {
|
||||
for (var i = 0; i < tracks.length; i++){
|
||||
tracks[i].album = {
|
||||
name: album.name,
|
||||
uri: album.uri
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(coreActions.albumLoaded(album));
|
||||
dispatch(coreActions.tracksLoaded(tracks));
|
||||
|
||||
// now get all the artists for this album (full objects)
|
||||
// we do this to get the artist artwork
|
||||
@ -1535,19 +1525,24 @@ export function getPlaylist(uri){
|
||||
description = description.split('<a href="spotify:user:').join('<a href="#'+global.baseURL+'user/spotify:user:')
|
||||
}
|
||||
|
||||
var tracks = helpers.formatTracks(response.tracks.items);
|
||||
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
response,
|
||||
helpers.formatPlaylist(response),
|
||||
{
|
||||
is_completely_loaded: true,
|
||||
can_edit: (getState().spotify.me && response.owner.id == getState().spotify.me.id),
|
||||
tracks: helpers.formatTracks(response.tracks.items),
|
||||
user_uri: response.owner.uri,
|
||||
tracks_uris: helpers.arrayOf('uri', tracks),
|
||||
tracks_more: response.tracks.next,
|
||||
tracks_total: response.tracks.total,
|
||||
description: description
|
||||
}
|
||||
)
|
||||
|
||||
//dispatch(coreActions.userLoaded(helpers.formatUser(response.owner)));
|
||||
dispatch(coreActions.tracksLoaded(tracks));
|
||||
dispatch(coreActions.playlistLoaded(playlist));
|
||||
},
|
||||
error => {
|
||||
|
||||
Reference in New Issue
Block a user