Playlists have their own play() function; If HTTP API, then preload and then enqueue in batches
This commit is contained in:
@ -169,6 +169,11 @@ class ContextMenu extends React.Component{
|
||||
this.props.mopidyActions.playURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
}
|
||||
|
||||
playPlaylist(e){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.mopidyActions.playPlaylist(this.props.menu.uris[0])
|
||||
}
|
||||
|
||||
addToQueue(e, next = false){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.mopidyActions.enqueueURIs(this.props.menu.uris, this.props.menu.tracklist_uri, next)
|
||||
@ -326,6 +331,14 @@ class ContextMenu extends React.Component{
|
||||
</span>
|
||||
)
|
||||
|
||||
var play_playlist = (
|
||||
<span className="menu-item-wrapper">
|
||||
<a className="menu-item" onClick={e => this.playPlaylist(e)}>
|
||||
<span className="label">Play</span>
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
|
||||
var play_queue_item = (
|
||||
<span className="menu-item-wrapper">
|
||||
<a className="menu-item" onClick={e => this.playQueueItem(e)}>
|
||||
@ -446,7 +459,7 @@ class ContextMenu extends React.Component{
|
||||
case 'playlist':
|
||||
return (
|
||||
<div>
|
||||
{play_uris}
|
||||
{play_playlist}
|
||||
{this.canBeInLibrary() ? toggle_in_library : null}
|
||||
{context.source == 'spotify' ? go_to_user : null}
|
||||
{copy_uris}
|
||||
|
||||
@ -67,6 +67,20 @@ export function enqueueURIs( uris, from_uri = null, next = false, at_position =
|
||||
}
|
||||
}
|
||||
|
||||
export function playPlaylist(uri){
|
||||
return {
|
||||
type: 'MOPIDY_PLAY_PLAYLIST',
|
||||
uri: uri
|
||||
}
|
||||
}
|
||||
|
||||
export function playAlbum(uri){
|
||||
return {
|
||||
type: 'MOPIDY_PLAY_ALBUM',
|
||||
uri: uri
|
||||
}
|
||||
}
|
||||
|
||||
export function removeTracks( tlids ){
|
||||
return {
|
||||
type: 'MOPIDY_INSTRUCT',
|
||||
|
||||
@ -4,8 +4,9 @@ import * as helpers from '../../helpers'
|
||||
|
||||
var mopidyActions = require('./actions.js')
|
||||
var uiActions = require('../ui/actions.js')
|
||||
var lastfmActions = require('../lastfm/actions.js')
|
||||
var spotifyActions = require('../spotify/actions.js')
|
||||
var pusherActions = require('../pusher/actions.js')
|
||||
var lastfmActions = require('../lastfm/actions.js')
|
||||
|
||||
const MopidyMiddleware = (function(){
|
||||
|
||||
@ -219,7 +220,42 @@ const MopidyMiddleware = (function(){
|
||||
icon: (store.getState().ui.current_track ? helpers.getTrackIcon( store.getState().ui.current_track ) : false)
|
||||
}
|
||||
store.dispatch( pusherActions.deliverBroadcast(data) )
|
||||
break;
|
||||
break
|
||||
|
||||
case 'MOPIDY_PLAY_PLAYLIST':
|
||||
if (helpers.uriSource(action.uri) == 'spotify'){
|
||||
|
||||
// playlist already in index
|
||||
if (store.getState().ui.playlists.hasOwnProperty(action.uri)){
|
||||
|
||||
// make sure we didn't get this playlist from Mopidy-Spotify
|
||||
// if we did, we'd have a cached version on server so no need to fetch
|
||||
if (!store.getState().ui.playlists[action.uri].is_mopidy){
|
||||
store.dispatch(uiActions.startProcess('MOPIDY_ENQUEUE_URIS', 'Fetching tracks'))
|
||||
store.dispatch(spotifyActions.getAllPlaylistTracks(action.uri))
|
||||
break
|
||||
}
|
||||
|
||||
// not loaded, so we need to fetch
|
||||
} else {
|
||||
store.dispatch(uiActions.startProcess('MOPIDY_ENQUEUE_URIS', 'Fetching tracks'))
|
||||
store.dispatch(spotifyActions.getAllPlaylistTracks(action.uri))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// default to load it as per usual
|
||||
store.dispatch(mopidyActions.playURIs([action.uri], action.uri))
|
||||
|
||||
break
|
||||
|
||||
case 'SPOTIFY_ALL_PLAYLIST_TRACKS_LOADED_FOR_PLAYING':
|
||||
var uris = []
|
||||
for (var i = 0; i < action.tracks.length; i++){
|
||||
uris.push(action.tracks[i].track.uri)
|
||||
}
|
||||
store.dispatch(mopidyActions.playURIs(uris, action.uri))
|
||||
break
|
||||
|
||||
case 'MOPIDY_ENQUEUE_URIS':
|
||||
var uris_added = 0
|
||||
@ -273,7 +309,7 @@ const MopidyMiddleware = (function(){
|
||||
}
|
||||
store.dispatch(pusherActions.addQueueMetadata(tlids, action.from_uri))
|
||||
|
||||
// still more URIs? run again in 200ms
|
||||
// still more URIs? run again in 100ms
|
||||
// this gives our server time to handle other requests
|
||||
// crude, but prevents locking the server
|
||||
if (remaining_uris.length > 0){
|
||||
@ -281,7 +317,7 @@ const MopidyMiddleware = (function(){
|
||||
function(){
|
||||
process_batch()
|
||||
},
|
||||
200
|
||||
100
|
||||
)
|
||||
|
||||
// all done
|
||||
@ -306,45 +342,35 @@ const MopidyMiddleware = (function(){
|
||||
|
||||
var first_uri = action.uris[0]
|
||||
|
||||
// spotify playlist and albums are handled differently
|
||||
if (helpers.uriSource(first_uri) == 'spotify'){
|
||||
switch (helpers.uriType(first_uri)){
|
||||
case 'playlist':
|
||||
// TODO
|
||||
// trigger loading of all the playlist tracks
|
||||
// once loaded, re-run play uris
|
||||
// maybe create new play_album play_playlist actions to handle
|
||||
// as we'd then reuse play_uris for the loaded track uris
|
||||
break
|
||||
|
||||
case 'album':
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// add our first track
|
||||
instruct( socket, store, 'tracklist.add', { uri: first_uri, at_position: 0 } )
|
||||
.then( response => {
|
||||
instruct(socket, store, 'tracklist.add', { uri: first_uri, at_position: 0 })
|
||||
.then(response => {
|
||||
|
||||
// treat empty response as a failed lookup
|
||||
if( !response || response.length <= 0 ){
|
||||
store.dispatch( uiActions.createNotification('Failed to load URI(s)', 'bad') )
|
||||
console.error(action)
|
||||
}else{
|
||||
// play it
|
||||
store.dispatch( mopidyActions.changeTrack( response[0].tlid ) );
|
||||
// play it (only if we got a successful lookup)
|
||||
if (response.length > 0){
|
||||
store.dispatch(mopidyActions.changeTrack(response[0].tlid));
|
||||
|
||||
var tlids = []
|
||||
for (var i = 0; i < response.length; i++){
|
||||
tlids.push(response[i].tlid)
|
||||
}
|
||||
store.dispatch( pusherActions.addQueueMetadata(tlids, action.from_uri) )
|
||||
store.dispatch(pusherActions.addQueueMetadata(tlids, action.from_uri))
|
||||
} else {
|
||||
store.dispatch(uiActions.createNotification('Failed to add some URI(s)', 'bad'))
|
||||
}
|
||||
|
||||
// add the rest of our uris (if any)
|
||||
action.uris.shift();
|
||||
if( action.uris.length > 0 ){
|
||||
store.dispatch( mopidyActions.enqueueURIs( action.uris, action.from_uri, 1 ) )
|
||||
}
|
||||
// add the rest of our uris (if any)
|
||||
action.uris.shift();
|
||||
if( action.uris.length > 0 ){
|
||||
|
||||
// wait 100ms so the server can trigger track_changed etc
|
||||
// this means our UI feels snappier as the first track shows up quickly
|
||||
setTimeout(
|
||||
function(){
|
||||
store.dispatch(mopidyActions.enqueueURIs( action.uris, action.from_uri, 1 ))
|
||||
},
|
||||
100
|
||||
)
|
||||
}
|
||||
})
|
||||
break;
|
||||
@ -490,7 +516,8 @@ const MopidyMiddleware = (function(){
|
||||
type: 'playlist',
|
||||
name: response.name,
|
||||
uri: response.uri,
|
||||
source: (source == 'spotify' ? 'local' : source),
|
||||
source: source,
|
||||
is_mopidy: true,
|
||||
last_modified: response.last_modified,
|
||||
tracks_total: ( response.tracks ? response.tracks.length : 0 )
|
||||
}
|
||||
@ -514,6 +541,7 @@ const MopidyMiddleware = (function(){
|
||||
response,
|
||||
{
|
||||
type: 'playlist',
|
||||
is_mopidy: true,
|
||||
tracks: ( response.tracks ? response.tracks : [] ),
|
||||
tracks_total: ( response.tracks ? response.tracks.length : [] )
|
||||
}
|
||||
@ -738,6 +766,7 @@ const MopidyMiddleware = (function(){
|
||||
var album = Object.assign(
|
||||
{},
|
||||
{
|
||||
is_mopidy: true,
|
||||
artists: response[uri][0].artists,
|
||||
tracks: response[uri],
|
||||
tracks_total: response[uri].length
|
||||
@ -766,6 +795,7 @@ const MopidyMiddleware = (function(){
|
||||
{ images: [] },
|
||||
response[0].album,
|
||||
{
|
||||
is_mopidy: true,
|
||||
artists: response[0].artists,
|
||||
tracks: response,
|
||||
tracks_total: response.length
|
||||
@ -869,6 +899,7 @@ const MopidyMiddleware = (function(){
|
||||
{},
|
||||
(response ? response[0].artists[0] : {}),
|
||||
{
|
||||
is_mopidy: true,
|
||||
albums_uris: helpers.asURIs(albums),
|
||||
tracks: response.slice(0,10)
|
||||
}
|
||||
|
||||
@ -890,7 +890,7 @@ export function createPlaylist( name, is_public ){
|
||||
}
|
||||
}
|
||||
|
||||
export function savePlaylist( uri, name, is_public ){
|
||||
export function savePlaylist(uri, name, is_public){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
sendRequest( dispatch, getState, 'users/'+ getState().spotify.me.id +'/playlists/'+ helpers.getFromUri('playlistid',uri), 'PUT', { name: name, public: is_public } )
|
||||
@ -906,7 +906,7 @@ export function savePlaylist( uri, name, is_public ){
|
||||
}
|
||||
}
|
||||
|
||||
export function getPlaylist( uri ){
|
||||
export function getPlaylist(uri){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// get the main playlist object
|
||||
@ -943,7 +943,44 @@ export function getPlaylist( uri ){
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextPlaylistsBatch( dispatch, getState, playlists, lastResponse ){
|
||||
/**
|
||||
* Get all tracks for a playlist
|
||||
*
|
||||
* Recursively get .next until we have all tracks
|
||||
**/
|
||||
function loadNextPlaylistTracksBatch(dispatch, getState, uri, tracks, lastResponse){
|
||||
if( lastResponse.next ){
|
||||
sendRequest(dispatch, getState, lastResponse.next)
|
||||
.then( response => {
|
||||
tracks = [...tracks, ...response.items]
|
||||
loadNextPlaylistTracksBatch(dispatch, getState, uri, tracks, response)
|
||||
});
|
||||
}else{
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ALL_PLAYLIST_TRACKS_LOADED_FOR_PLAYING',
|
||||
uri: uri,
|
||||
tracks: tracks
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getAllPlaylistTracks(uri){
|
||||
return (dispatch, getState) => {
|
||||
sendRequest(dispatch, getState, 'users/'+ helpers.getFromUri('userid',uri) +'/playlists/'+ helpers.getFromUri('playlistid',uri) +'/tracks?market='+getState().spotify.country)
|
||||
.then( response => {
|
||||
loadNextPlaylistTracksBatch(dispatch, getState, uri, response.items, response)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of our playlists in one foul swoop
|
||||
*
|
||||
* Recursively gets playlists until no more .next value. Fails when user has
|
||||
* a lot of playlists, and we hit the API limits
|
||||
**/
|
||||
function loadNextPlaylistsBatch(dispatch, getState, playlists, lastResponse){
|
||||
if( lastResponse.next ){
|
||||
sendRequest( dispatch, getState, lastResponse.next )
|
||||
.then( response => {
|
||||
@ -967,7 +1004,7 @@ export function getAllLibraryPlaylists(){
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleFollowingPlaylist( uri, method ){
|
||||
export function toggleFollowingPlaylist(uri, method){
|
||||
if( method == 'PUT' ) var new_state = 1
|
||||
if( method == 'DELETE' ) var new_state = 0
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ class Playlist extends React.Component{
|
||||
|
||||
play(){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Play', label: this.props.playlist.uri })
|
||||
this.props.mopidyActions.playURIs([this.props.playlist.uri], this.props.params.uri)
|
||||
this.props.mopidyActions.playPlaylist(this.props.playlist.uri)
|
||||
}
|
||||
|
||||
follow(){
|
||||
|
||||
Reference in New Issue
Block a user