Tracks and Queue overhaul
This commit is contained in:
@ -81,8 +81,8 @@ export function set(data){
|
||||
**/
|
||||
|
||||
export function reorderPlaylistTracks(uri, indexes, insert_before, snapshot_id = false){
|
||||
var range = helpers.createRange(indexes );
|
||||
switch(helpers.uriSource(uri )){
|
||||
var range = helpers.createRange(indexes);
|
||||
switch(helpers.uriSource(uri)){
|
||||
|
||||
case 'spotify':
|
||||
return {
|
||||
|
||||
@ -186,81 +186,6 @@ const CoreMiddleware = (function(){
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'MOPIDY_CURRENTTLTRACK':
|
||||
if (action.data && action.data.track){
|
||||
helpers.setWindowTitle(action.data.track, store.getState().mopidy.play_state);
|
||||
|
||||
// make sure our images use mopidy host:port
|
||||
if (action.data.track.album && action.data.track.album.images && action.data.track.album.images.length > 0){
|
||||
var images = Object.assign([], action.data.track.album.images)
|
||||
for (var i = 0; i < images.length; i++){
|
||||
if (typeof(images[i]) === 'string' && images[i].startsWith('/images/')){
|
||||
images[i] = '//'+store.getState().mopidy.host+':'+store.getState().mopidy.port+images[i]
|
||||
}
|
||||
}
|
||||
action.data.track.album.images = images
|
||||
}
|
||||
}
|
||||
|
||||
var current_tracklist = []
|
||||
Object.assign(current_tracklist, core.current_tracklist)
|
||||
|
||||
for (var i = 0; i < current_tracklist.length; i++){
|
||||
Object.assign(
|
||||
current_tracklist[i],
|
||||
{ playing: (current_tracklist[i].tlid == action.data.tlid) }
|
||||
)
|
||||
}
|
||||
|
||||
// Update action
|
||||
action.current_tracklist = current_tracklist;
|
||||
action.current_track = action.data.track.uri;
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'MOPIDY_TLTRACKS':
|
||||
var core = store.getState().core;
|
||||
var tracklist = []
|
||||
for (var i = 0; i < action.data.length; i++){
|
||||
|
||||
var tltrack = helpers.formatTracks(action.data[i]);
|
||||
|
||||
// load our metadata (if we have any for that tlid)
|
||||
if (core.queue_metadata !== undefined && core.queue_metadata['tlid_'+tltrack.tlid] !== undefined){
|
||||
var metadata = core.queue_metadata['tlid_'+tltrack.tlid]
|
||||
} else {
|
||||
var metadata = {}
|
||||
}
|
||||
|
||||
var current_tlid = null;
|
||||
if (core.current_track && core.tracks && core.tracks[core.current_track] !== undefined && core.tracks[core.current_track].tlid !== undefined){
|
||||
current_tlid = core.tracks[core.current_track].tlid;
|
||||
}
|
||||
|
||||
var track = Object.assign(
|
||||
{},
|
||||
tltrack,
|
||||
metadata,
|
||||
{
|
||||
playing: (tltrack.tlid == current_tlid)
|
||||
})
|
||||
tracklist.push(track)
|
||||
}
|
||||
|
||||
// Append to our action
|
||||
tracklist = helpers.formatTracks(tracklist);
|
||||
action.tracklist = tracklist;
|
||||
|
||||
// Load our tracks into index
|
||||
store.dispatch({
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: tracklist
|
||||
});
|
||||
|
||||
next(action);
|
||||
break
|
||||
|
||||
// Get assets from all of our providers
|
||||
case 'GET_LIBRARY_PLAYLISTS':
|
||||
if (store.getState().spotify.connected){
|
||||
@ -295,8 +220,115 @@ const CoreMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'RESTART':
|
||||
location.reload()
|
||||
break
|
||||
location.reload();
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* Playlist manipulation
|
||||
**/
|
||||
|
||||
case 'PLAYLIST_KEY_UPDATED':
|
||||
var playlists = Object.assign({}, core.playlists);
|
||||
|
||||
if (playlists[action.key] === undefined){
|
||||
dispatch(coreActions.handleException("Cannot change key of playlist not in index"));
|
||||
}
|
||||
|
||||
// Delete our old playlist by key, and add by new key
|
||||
var playlist = Object.assign({}, playlists[action.key]);
|
||||
delete playlists[action.key];
|
||||
playlists[action.new_key] = playlist;
|
||||
|
||||
store.dispatch({
|
||||
type: 'UPDATE_PLAYLISTS_INDEX',
|
||||
playlists: playlists
|
||||
});
|
||||
break;
|
||||
|
||||
case 'PLAYLIST_TRACKS_REORDERED':
|
||||
var playlists = Object.assign({}, core.playlists);
|
||||
var playlist = Object.assign({}, playlists[action.key]);
|
||||
var tracks_uris = Object.assign([], playlist.tracks_uris);
|
||||
|
||||
// handle insert_before offset if we're moving BENEATH where we're slicing tracks
|
||||
var insert_before = action.insert_before
|
||||
if (insert_before > action.range_start){
|
||||
insert_before = insert_before - action.range_length;
|
||||
}
|
||||
|
||||
// cut our moved tracks into a new array
|
||||
var tracks_to_move = tracks_uris.splice(action.range_start, action.range_length)
|
||||
tracks_to_move.reverse()
|
||||
|
||||
for (i = 0; i < tracks_to_move.length; i++){
|
||||
tracks_uris.splice(insert_before, 0, tracks_to_move[i])
|
||||
}
|
||||
|
||||
var snapshot_id = null;
|
||||
if (action.snapshot_id){
|
||||
snapshot_id = action.snapshot_id;
|
||||
}
|
||||
|
||||
// Update our playlist
|
||||
playlist.tracks_uris = tracks_uris;
|
||||
playlist.snapshot_id = snapshot_id;
|
||||
|
||||
// Trigger normal playlist updating
|
||||
store.dispatch({
|
||||
type: 'PLAYLISTS_LOADED',
|
||||
playlists: [playlist]
|
||||
});
|
||||
break;
|
||||
|
||||
case 'PLAYLIST_TRACKS_REMOVED':
|
||||
var playlists = Object.assign({}, core.playlists);
|
||||
var playlist = Object.assign({}, playlists[action.key]);
|
||||
var tracks_uris = Object.assign([], playlist.tracks_uris);
|
||||
|
||||
var indexes = action.tracks_indexes.reverse()
|
||||
for(var i = 0; i < indexes.length; i++){
|
||||
tracks_uris.splice(indexes[i], 1);
|
||||
}
|
||||
|
||||
var snapshot_id = null;
|
||||
if (action.snapshot_id){
|
||||
snapshot_id = action.snapshot_id;
|
||||
}
|
||||
|
||||
// Update our playlist
|
||||
playlist.tracks_uris = tracks_uris;
|
||||
playlist.snapshot_id = snapshot_id;
|
||||
|
||||
// Trigger normal playlist updating
|
||||
store.dispatch({
|
||||
type: 'PLAYLISTS_LOADED',
|
||||
playlists: [playlist]
|
||||
});
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* Queue and playback info
|
||||
**/
|
||||
|
||||
case 'CURRENT_TRACK_LOADED':
|
||||
store.dispatch({
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: [action.current_track]
|
||||
});
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'QUEUE_LOADED':
|
||||
store.dispatch({
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: action.tracks
|
||||
});
|
||||
|
||||
action.tracks_uris = helpers.arrayOf('uri',action.tracks);
|
||||
next(action);
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
@ -309,8 +341,7 @@ const CoreMiddleware = (function(){
|
||||
store.dispatch({
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: [action.track]
|
||||
})
|
||||
next(action);
|
||||
});
|
||||
break;
|
||||
|
||||
// Array wrapper for ALBUMS_LOADED
|
||||
@ -319,7 +350,6 @@ const CoreMiddleware = (function(){
|
||||
type: 'ALBUMS_LOADED',
|
||||
albums: [action.album]
|
||||
});
|
||||
next(action);
|
||||
break;
|
||||
|
||||
// Array wrapper for ARTISTS_LOADED
|
||||
@ -328,7 +358,6 @@ const CoreMiddleware = (function(){
|
||||
type: 'ARTISTS_LOADED',
|
||||
artists: [action.artist]
|
||||
});
|
||||
next(action);
|
||||
break;
|
||||
|
||||
// Array wrapper for PLAYLISTS_LOADED
|
||||
@ -337,7 +366,6 @@ const CoreMiddleware = (function(){
|
||||
type: 'PLAYLISTS_LOADED',
|
||||
playlists: [action.playlist]
|
||||
});
|
||||
next(action);
|
||||
break;
|
||||
|
||||
// Array wrapper for USERS_LOADED
|
||||
@ -346,7 +374,6 @@ const CoreMiddleware = (function(){
|
||||
type: 'USERS_LOADED',
|
||||
users: [action.user]
|
||||
});
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'TRACKS_LOADED':
|
||||
@ -361,6 +388,7 @@ const CoreMiddleware = (function(){
|
||||
|
||||
if (track.album && track.album.images && track.album.images.length > 0){
|
||||
track.album.images = helpers.digestMopidyImages(store.getState().mopidy, track.album.images);
|
||||
track.images = track.album.images;
|
||||
}
|
||||
|
||||
tracks[track.uri] = track;
|
||||
@ -523,7 +551,7 @@ const CoreMiddleware = (function(){
|
||||
user = Object.assign({}, users[user.uri], user);
|
||||
}
|
||||
|
||||
users[action.key] = user;
|
||||
users[user.uri] = user;
|
||||
}
|
||||
|
||||
// Update index
|
||||
@ -542,6 +570,7 @@ const CoreMiddleware = (function(){
|
||||
**/
|
||||
|
||||
case 'LOADED_MORE':
|
||||
console.log(action);
|
||||
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]);
|
||||
@ -569,7 +598,10 @@ const CoreMiddleware = (function(){
|
||||
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];
|
||||
var uris = records_uris;
|
||||
if (parent[records_type_plural+'_uris'] !== undefined){
|
||||
uris = [...parent[records_type_plural+'_uris'], ...uris];
|
||||
}
|
||||
parent[records_type_plural+'_uris'] = uris;
|
||||
if (action.records_data.next !== undefined){
|
||||
parent[records_type_plural+'_more'] = action.records_data.next;
|
||||
|
||||
@ -11,19 +11,14 @@ export default function reducer(core = {}, action){
|
||||
* Current track and tracklist
|
||||
**/
|
||||
|
||||
case 'MOPIDY_TLTRACKS':
|
||||
if (!action.tracklist){
|
||||
return core;
|
||||
}
|
||||
return Object.assign({}, core, { current_tracklist: action.tracklist });
|
||||
|
||||
case 'MOPIDY_CURRENTTLTRACK':
|
||||
if (!action.data){
|
||||
return core;
|
||||
}
|
||||
case 'CURRENT_TRACK_LOADED':
|
||||
return Object.assign({}, core, {
|
||||
current_tracklist: action.current_tracklist,
|
||||
current_track: action.current_track
|
||||
current_track_uri: action.current_track_uri
|
||||
});
|
||||
|
||||
case 'QUEUE_LOADED':
|
||||
return Object.assign({}, core, {
|
||||
queue: action.tracks_uris
|
||||
});
|
||||
|
||||
case 'PUSHER_QUEUE_METADATA':
|
||||
@ -190,50 +185,6 @@ export default function reducer(core = {}, action){
|
||||
* Playlists
|
||||
**/
|
||||
|
||||
case 'PLAYLIST_KEY_UPDATED':
|
||||
var playlists = Object.assign([], core.playlists)
|
||||
|
||||
// URI not in our index? No change needed then
|
||||
if (typeof(playlists[action.key]) === 'undefined'){
|
||||
return core
|
||||
}
|
||||
|
||||
// Delete our old playlist by key, and add by new key
|
||||
var playlist = Object.assign({}, playlists[action.key])
|
||||
delete playlists[action.key]
|
||||
playlists[playlist.uri] = playlist
|
||||
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'PLAYLIST_LOADED_MORE_TRACKS':
|
||||
var playlists = Object.assign([], core.playlists)
|
||||
var playlist = Object.assign(
|
||||
{},
|
||||
playlists[action.key],
|
||||
{
|
||||
tracks: [...playlists[action.key].tracks, ...helpers.formatTracks(action.data.items)],
|
||||
tracks_more: action.data.next,
|
||||
tracks_total: action.data.total
|
||||
}
|
||||
)
|
||||
|
||||
playlists[action.key] = playlist
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'PLAYLIST_TRACKS_REMOVED':
|
||||
var playlists = Object.assign([], core.playlists)
|
||||
var playlist = Object.assign({}, playlists[action.key])
|
||||
var tracks = Object.assign([], playlist.tracks)
|
||||
var indexes = action.tracks_indexes.reverse()
|
||||
for(var i = 0; i < indexes.length; i++){
|
||||
tracks.splice(indexes[i], 1 )
|
||||
}
|
||||
var snapshot_id = null
|
||||
if (action.snapshot_id ) snapshot_id = action.snapshot_id
|
||||
Object.assign(playlist, { tracks: tracks, snapshot_id: snapshot_id })
|
||||
playlists[action.key] = playlist
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'PLAYLIST_TRACKS':
|
||||
var playlists = Object.assign([], core.playlists)
|
||||
var playlist = Object.assign({}, playlists[action.key], { tracks: helpers.formatTracks(action.tracks) })
|
||||
@ -241,29 +192,6 @@ export default function reducer(core = {}, action){
|
||||
playlists[action.key] = playlist
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'PLAYLIST_TRACKS_REORDERED':
|
||||
var playlists = Object.assign([], core.playlists)
|
||||
var playlist = Object.assign({}, playlists[action.key])
|
||||
var tracks = Object.assign([], playlist.tracks)
|
||||
|
||||
// handle insert_before offset if we're moving BENEATH where we're slicing tracks
|
||||
var insert_before = action.insert_before
|
||||
if (insert_before > action.range_start ) insert_before = insert_before - action.range_length
|
||||
|
||||
// cut our moved tracks into a new array
|
||||
var tracks_to_move = tracks.splice(action.range_start, action.range_length)
|
||||
tracks_to_move.reverse()
|
||||
|
||||
for(i = 0; i < tracks_to_move.length; i++){
|
||||
tracks.splice(insert_before, 0, tracks_to_move[i])
|
||||
}
|
||||
|
||||
var snapshot_id = null
|
||||
if (action.snapshot_id ) snapshot_id = action.snapshot_id
|
||||
Object.assign(playlist, { tracks: tracks, snapshot_id: snapshot_id })
|
||||
playlists[action.key] = playlist
|
||||
return Object.assign({}, core, { playlists: playlists });
|
||||
|
||||
case 'LIBRARY_PLAYLISTS_LOADED':
|
||||
if (core.library_playlists){
|
||||
var library_playlists = [...core.library_playlists, ...action.uris]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
var coreActions = require('../core/actions')
|
||||
var uiActions = require('../ui/actions')
|
||||
var helpers = require('../../helpers')
|
||||
var coreActions = require('../core/actions');
|
||||
var uiActions = require('../ui/actions');
|
||||
var helpers = require('../../helpers');
|
||||
|
||||
/**
|
||||
* Send an ajax request to the LastFM API
|
||||
@ -150,34 +150,9 @@ export function revokeAuthorization(){
|
||||
return { type: 'LASTFM_AUTHORIZATION_REVOKED' }
|
||||
}
|
||||
|
||||
export function connect(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'LASTFM_CONNECTING' });
|
||||
|
||||
// Authorized? Multi-purpose our connection test to get the current user
|
||||
if (getState().lastfm.session){
|
||||
dispatch(getMe());
|
||||
|
||||
// Not authorized? Just use a generic lookup to test our connection
|
||||
} else {
|
||||
sendRequest(dispatch, getState, 'method=artist.getInfo&artist=Moby')
|
||||
.then(
|
||||
response => {
|
||||
dispatch({ type: 'LASTFM_CONNECTED' })
|
||||
},
|
||||
error => {
|
||||
dispatch({ type: 'LASTFM_DISCONNECTED' })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signed requests
|
||||
* TODO
|
||||
**/
|
||||
|
||||
export function loveTrack(uri, artist, track){
|
||||
@ -218,6 +193,35 @@ export function unloveTrack(uri, artist, track){
|
||||
}
|
||||
}
|
||||
|
||||
export function scrobble(track){
|
||||
return (dispatch, getState) => {
|
||||
var track_name = track.name;
|
||||
var artist_name = "Unknown";
|
||||
if (track.artists){
|
||||
artist_name = track.artists[0].name;
|
||||
}
|
||||
var artist_name = encodeURIComponent(artist_name);
|
||||
|
||||
var params = 'method=track.scrobble';
|
||||
params += '&track='+track_name+'&artist='+artist_name;
|
||||
params += '×tamp='+Math.floor(Date.now() / 1000);
|
||||
|
||||
sendSignedRequest(dispatch, getState, params)
|
||||
.then(
|
||||
response => {
|
||||
console.log("Scrobbled", response);
|
||||
},
|
||||
error => {
|
||||
dispatch(coreActions.handleException(
|
||||
'Could not scrobble track',
|
||||
error,
|
||||
(error.description ? error.description : null)
|
||||
));
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non-signed requests
|
||||
@ -331,32 +335,3 @@ export function getTrack(track, artist_name = null, track_name = null){
|
||||
}
|
||||
}
|
||||
|
||||
export function scrobble(track){
|
||||
return (dispatch, getState) => {
|
||||
var track_name = track.name;
|
||||
var artist_name = "Unknown";
|
||||
if (track.artists){
|
||||
artist_name = track.artists[0].name;
|
||||
}
|
||||
var artist_name = encodeURIComponent(artist_name);
|
||||
|
||||
var params = 'method=track.scrobble';
|
||||
params += '&track='+track_name+'&artist='+artist_name;
|
||||
params += '×tamp='+Math.floor(Date.now() / 1000);
|
||||
|
||||
sendSignedRequest(dispatch, getState, params)
|
||||
.then(
|
||||
response => {
|
||||
console.log("Scrobbled", response);
|
||||
},
|
||||
error => {
|
||||
dispatch(coreActions.handleException(
|
||||
'Could not scrobble track',
|
||||
error,
|
||||
(error.description ? error.description : null)
|
||||
));
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1259,11 +1259,11 @@ const MopidyMiddleware = (function(){
|
||||
type: 'PLAYLIST_KEY_UPDATED',
|
||||
key: action.key,
|
||||
new_key: response.uri
|
||||
})
|
||||
hashHistory.push(global.baseURL+'playlist/'+response.uri)
|
||||
});
|
||||
hashHistory.push(global.baseURL+'playlist/'+encodeURIComponent(response.uri));
|
||||
}
|
||||
|
||||
store.dispatch(uiActions.createNotification('Saved'))
|
||||
store.dispatch(uiActions.createNotification('Saved'));
|
||||
})
|
||||
});
|
||||
break
|
||||
@ -1703,17 +1703,17 @@ const MopidyMiddleware = (function(){
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
case 'MOPIDY_TLTRACKS':
|
||||
store.dispatch({
|
||||
type: 'QUEUE_LOADED',
|
||||
tracks: helpers.formatTracks(action.data)
|
||||
})
|
||||
break;
|
||||
|
||||
case 'MOPIDY_CURRENTTLTRACK':
|
||||
if (action.data && action.data.track){
|
||||
var track = helpers.formatTracks(action.data);
|
||||
|
||||
// Fire off our universal track index loader
|
||||
store.dispatch({
|
||||
type: 'TRACK_LOADED',
|
||||
key: track.uri,
|
||||
track: track
|
||||
});
|
||||
|
||||
// We've got Spotify running, and it's a spotify track - go straight to the source!
|
||||
if (helpers.uriSource(track.uri) == 'spotify' && store.getState().spotify.enabled){
|
||||
store.dispatch(spotifyActions.getTrack(track.uri))
|
||||
@ -1722,9 +1722,16 @@ const MopidyMiddleware = (function(){
|
||||
} else {
|
||||
store.dispatch(mopidyActions.getImages('tracks',[track.uri]))
|
||||
}
|
||||
}
|
||||
|
||||
next(action);
|
||||
// Set our window title to the track title
|
||||
helpers.setWindowTitle(track, store.getState().mopidy.play_state);
|
||||
|
||||
store.dispatch({
|
||||
type: 'CURRENT_TRACK_LOADED',
|
||||
current_track: track,
|
||||
current_track_uri: track.uri
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'MOPIDY_GET_TRACK':
|
||||
|
||||
@ -232,10 +232,6 @@ export function importAuthorization(data){
|
||||
**/
|
||||
export function getMe(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ME_LOADED', data: false });
|
||||
|
||||
sendRequest(dispatch, getState, 'me' )
|
||||
.then(
|
||||
response => {
|
||||
@ -1192,7 +1188,7 @@ export function playArtistTopTracks(uri){
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
export function getUser(uri){
|
||||
export function getUser(uri, and_playlists = false){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// get the user
|
||||
@ -1212,7 +1208,9 @@ export function getUser(uri){
|
||||
}
|
||||
)
|
||||
|
||||
dispatch(getUserPlaylists(uri))
|
||||
if (and_playlists){
|
||||
dispatch(getUserPlaylists(uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1242,14 +1240,11 @@ export function getUserPlaylists(user_uri){
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'PLAYLISTS_LOADED',
|
||||
playlists: playlists
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: 'SPOTIFY_USER_PLAYLISTS_LOADED',
|
||||
key: user_uri,
|
||||
data: response
|
||||
type: 'LOADED_MORE',
|
||||
parent_type: 'user',
|
||||
parent_key: user_uri,
|
||||
records_type: 'playlist',
|
||||
records_data: response
|
||||
});
|
||||
},
|
||||
error => {
|
||||
|
||||
@ -415,7 +415,7 @@ const SpotifyMiddleware = (function(){
|
||||
store.dispatch({
|
||||
type: 'USERS_LOADED',
|
||||
users: [action.data]
|
||||
})
|
||||
});
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user