Tracks and Queue overhaul
This commit is contained in:
5
src/js/bootstrap.js
vendored
5
src/js/bootstrap.js
vendored
@ -32,8 +32,9 @@ let reducers = combineReducers({
|
||||
// TODO: Look at using propTypes in the component for these falsy initial states
|
||||
var initialState = {
|
||||
core: {
|
||||
current_tracklist: [],
|
||||
current_tltrack: false,
|
||||
queue: [],
|
||||
queue_metadata: {},
|
||||
current_track_uri: null,
|
||||
albums: {},
|
||||
artists: {},
|
||||
playlists: {},
|
||||
|
||||
@ -45,7 +45,7 @@ class LastfmAuthenticationFrame extends React.Component{
|
||||
|
||||
// Bounced with an error
|
||||
if (data.error !== undefined){
|
||||
this.props.uiActions.createNotification(data.error,'bad')
|
||||
this.props.uiActions.createNotification(data.message,'bad')
|
||||
|
||||
// No errors? We're in!
|
||||
} else {
|
||||
|
||||
@ -145,7 +145,7 @@ class Modal extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
current_track: (state.core.current_track !== undefined && state.core.tracks !== undefined && state.core.tracks[state.core.current_track] !== undefined ? state.core.tracks[state.core.current_track] : null),
|
||||
current_track: (state.core.tracks[state.core.current_track_uri] !== undefined ? state.core.tracks[state.core.current_track_uri] : null),
|
||||
uri_schemes: (state.mopidy.uri_schemes ? state.mopidy.uri_schemes : []),
|
||||
search_uri_schemes: (state.ui.search_uri_schemes ? state.ui.search_uri_schemes : []),
|
||||
volume: state.mopidy.volume,
|
||||
|
||||
@ -135,7 +135,7 @@ class PlaybackControls extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
current_track: (state.core.current_track !== undefined && state.core.tracks !== undefined && state.core.tracks[state.core.current_track] !== undefined ? state.core.tracks[state.core.current_track] : null),
|
||||
current_track: (state.core.tracks[state.core.current_track_uri] !== undefined ? state.core.tracks[state.core.current_track_uri] : null),
|
||||
radio_enabled: (state.ui.radio && state.ui.radio.enabled ? true : false),
|
||||
play_state: state.mopidy.play_state,
|
||||
time_position: state.mopidy.time_position,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -78,7 +78,14 @@ class Artist extends React.Component{
|
||||
}
|
||||
|
||||
loadMore(){
|
||||
this.props.spotifyActions.getURL(this.props.artist.albums_more, 'SPOTIFY_ARTIST_ALBUMS_LOADED', this.props.params.uri );
|
||||
this.props.spotifyActions.loadMore(
|
||||
this.props.artist.albums_more,
|
||||
{
|
||||
parent_type: 'artist',
|
||||
parent_key: this.props.params.uri,
|
||||
records_type: 'album'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
inLibrary(){
|
||||
@ -190,7 +197,7 @@ class Artist extends React.Component{
|
||||
<h4>Albums</h4>
|
||||
<section className="grid-wrapper no-top-padding">
|
||||
<AlbumGrid albums={albums} />
|
||||
<LazyLoadListener loading={this.props.artist.albums_more} loadMore={ () => this.loadMore() }/>
|
||||
<LazyLoadListener loading={this.props.artist.albums_more} loadMore={() => this.loadMore()} />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -14,6 +14,7 @@ import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import FollowButton from '../components/FollowButton'
|
||||
import Header from '../components/Header'
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger'
|
||||
import URILink from '../components/URILink'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as coreActions from '../services/core/actions'
|
||||
@ -101,20 +102,20 @@ class Playlist extends React.Component{
|
||||
|
||||
// TODO: Once deletion occurs, remove playlist from global playlists list
|
||||
delete(){
|
||||
this.props.mopidyActions.deletePlaylist(this.props.playlist.uri )
|
||||
this.props.mopidyActions.deletePlaylist(this.props.playlist.uri);
|
||||
}
|
||||
|
||||
reorderTracks(indexes, index){
|
||||
this.props.coreActions.reorderPlaylistTracks(this.props.playlist.uri, indexes, index, this.props.playlist.snapshot_id )
|
||||
this.props.coreActions.reorderPlaylistTracks(this.props.playlist.uri, indexes, index, this.props.playlist.snapshot_id);
|
||||
}
|
||||
|
||||
removeTracks(tracks_indexes){
|
||||
this.props.coreActions.removeTracksFromPlaylist(this.props.playlist.uri, tracks_indexes )
|
||||
this.props.coreActions.removeTracksFromPlaylist(this.props.playlist.uri, tracks_indexes);
|
||||
}
|
||||
|
||||
inLibrary(){
|
||||
var library = helpers.uriSource(this.props.params.uri)+'_library_playlists'
|
||||
return (this.props[library] && this.props[library].indexOf(this.props.params.uri) > -1)
|
||||
var library = helpers.uriSource(this.props.params.uri)+'_library_playlists';
|
||||
return (this.props[library] && this.props[library].indexOf(this.props.params.uri) > -1);
|
||||
}
|
||||
|
||||
renderActions(){
|
||||
@ -195,8 +196,8 @@ class Playlist extends React.Component{
|
||||
{ this.props.playlist.description ? <h2 className="description grey-text" dangerouslySetInnerHTML={{__html: this.props.playlist.description}}></h2> : null }
|
||||
|
||||
<ul className="details">
|
||||
{ !this.props.slim_mode ? <li className="has-tooltip"><FontAwesome name={helpers.sourceIcon(this.props.params.uri )} /><span className="tooltip">{helpers.uriSource(this.props.params.uri )} playlist</span></li> : null }
|
||||
{ this.props.playlist.owner && !this.props.slim_mode ? <li><Link to={'/user/'+this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</Link></li> : null }
|
||||
{ !this.props.slim_mode ? <li className="has-tooltip"><FontAwesome name={helpers.sourceIcon(this.props.params.uri )} /><span className="tooltip">{helpers.uriSource(this.props.params.uri)} playlist</span></li> : null }
|
||||
{ this.props.playlist.owner && !this.props.slim_mode ? <li><URILink type="user" uri={this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</URILink></li> : null }
|
||||
{ this.props.playlist.followers ? <li>{this.props.playlist.followers.total.toLocaleString()} followers</li> : null }
|
||||
{ this.props.playlist.last_modified ? <li>Edited <Dater type="ago" data={this.props.playlist.last_modified} /></li> : null }
|
||||
<li>
|
||||
|
||||
@ -92,6 +92,31 @@ class Queue extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
var tracks = [];
|
||||
if (this.props.queue && this.props.tracks){
|
||||
for (var i = 0; i < this.props.queue.length; i++){
|
||||
var uri = this.props.queue[i];
|
||||
if (this.props.tracks.hasOwnProperty(uri)){
|
||||
var track = this.props.tracks[uri];
|
||||
track.playing = (track.uri == this.props.current_track_uri);
|
||||
tracks.push(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge our metadata with each track
|
||||
for (var i = 0; i < tracks.length; i++){
|
||||
var track = tracks[i];
|
||||
if (this.props.queue_metadata["tlid_"+track.tlid] !== undefined){
|
||||
track = Object.assign(
|
||||
{},
|
||||
track,
|
||||
this.props.queue_metadata["tlid_"+track.tlid]
|
||||
);
|
||||
tracks[i] = track;
|
||||
}
|
||||
}
|
||||
|
||||
var options = (
|
||||
<span>
|
||||
{this.props.spotify_enabled ? <button className="no-hover" onClick={e => this.props.uiActions.openModal('edit_radio')}>
|
||||
@ -133,11 +158,11 @@ class Queue extends React.Component{
|
||||
show_source_icon={true}
|
||||
context="queue"
|
||||
className="queue-track-list"
|
||||
tracks={this.props.current_tracklist}
|
||||
removeTracks={tracks => this.removeTracks(tracks )}
|
||||
playTracks={tracks => this.playTracks(tracks )}
|
||||
playTrack={track => this.playTrack(track )}
|
||||
reorderTracks={(indexes, index) => this.reorderTracks(indexes, index) } />
|
||||
tracks={tracks}
|
||||
removeTracks={tracks => this.removeTracks(tracks)}
|
||||
playTracks={tracks => this.playTracks(tracks)}
|
||||
playTrack={track => this.playTrack(track)}
|
||||
reorderTracks={(indexes, index) => this.reorderTracks(indexes, index)} />
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -158,8 +183,11 @@ const mapStateToProps = (state, ownProps) => {
|
||||
spotify_enabled: state.spotify.enabled,
|
||||
radio: state.core.radio,
|
||||
radio_enabled: (state.core.radio && state.core.radio.enabled ? true : false),
|
||||
current_tracklist: state.core.current_tracklist,
|
||||
current_track: (state.core.current_track !== undefined && state.core.tracks !== undefined && state.core.tracks[state.core.current_track] !== undefined ? state.core.tracks[state.core.current_track] : null)
|
||||
tracks: state.core.tracks,
|
||||
queue: state.core.queue,
|
||||
queue_metadata: state.core.queue_metadata,
|
||||
current_track_uri: state.core.current_track_uri,
|
||||
current_track: (state.core.tracks[state.core.current_track_uri] !== undefined ? state.core.tracks[state.core.current_track_uri] : null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,18 +33,20 @@ class User extends React.Component{
|
||||
|
||||
loadUser(props = this.props){
|
||||
if (!props.user){
|
||||
this.props.spotifyActions.getUser(props.params.uri);
|
||||
this.props.spotifyActions.getUser(props.params.uri, true);
|
||||
this.props.spotifyActions.following(props.params.uri);
|
||||
}
|
||||
|
||||
// We got a user, but we haven't fetched their playlists yet
|
||||
if (props.user && !props.user.playlists_uris){
|
||||
this.props.spotifyActions.getUserPlaylists(props.params.uri);
|
||||
}
|
||||
}
|
||||
|
||||
loadMore(){
|
||||
this.props.spotifyActions.getURL(this.props.user.playlists_more, 'SPOTIFY_USER_PLAYLISTS_LOADED', this.props.params.uri);
|
||||
this.props.spotifyActions.loadMore(
|
||||
this.props.user.playlists_more,
|
||||
{
|
||||
parent_type: 'user',
|
||||
parent_key: this.props.params.uri,
|
||||
records_type: 'playlist'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
isMe(){
|
||||
@ -105,7 +107,7 @@ class User extends React.Component{
|
||||
<section className="grid-wrapper">
|
||||
<h4>Playlists</h4>
|
||||
<PlaylistGrid playlists={playlists} />
|
||||
<LazyLoadListener enabled={this.props.user.playlists_more} loadMore={ () => this.loadMore() }/>
|
||||
<LazyLoadListener loading={this.props.user.playlists_more} loadMore={() => this.loadMore()} />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -120,8 +122,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
me: state.spotify.me,
|
||||
playlists: state.core.playlists,
|
||||
user: (state.core.users && state.core.users[uri] !== undefined ? state.core.users[uri] : false),
|
||||
users: state.core.users
|
||||
user: (state.core.users[uri] !== undefined ? state.core.users[uri] : false)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user