Metadata operational; Handle cached/local lookups that are instant; Remove old tlids

This commit is contained in:
James Barnsley
2017-02-14 20:24:35 +13:00
parent 02d3868d1e
commit ef2f873295
14 changed files with 138 additions and 41 deletions

View File

@ -197,13 +197,13 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
# add queue metadata
def add_queue_metadata( self, tlids, from_uri, added_by ):
def add_queue_metadata( self, tlids, added_from, added_by ):
queue_metadata = self.queue_metadata
for tlid in tlids:
item = {
'tlid': tlid,
'from_uri': from_uri,
'added_from': added_from,
'added_by': added_by
}
queue_metadata['tlid_'+str(tlid)] = item

View File

@ -215,7 +215,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
elif messageJson['action'] == 'add_queue_metadata':
queue_metadata = self.frontend.add_queue_metadata(
messageJson['tlids'],
messageJson['from_uri'],
messageJson['added_from'],
connections[self.connectionid]['client']['username']
)

View File

@ -158,7 +158,7 @@ class ContextMenu extends React.Component{
]
break
case 'queue-track':
case 'queue':
var items = [
{ handleClick: 'playQueueItem', label: 'Play' },
{ handleClick: 'addToPlaylist', label: 'Add to playlist' },

View File

@ -57,22 +57,35 @@ export default class Track extends React.Component{
}
}
switch (track.type){
if (track.type == 'history'){
case 'history':
var track_columns = (
<span>
<span className="col name">
{ track.name ? track.name : <span className="grey-text">{track.uri}</span> }
</span>
<span className="col played_at">
{ track.played_at ? <span><Dater type="ago" data={track.played_at} /> ago</span> : null }
</span>
var track_columns = (
<span>
<span className="col name">
{ track.name ? track.name : <span className="grey-text">{track.uri}</span> }
</span>
)
break;
<span className="col played_at">
{ track.played_at ? <span><Dater type="ago" data={track.played_at} /> ago</span> : null }
</span>
</span>
)
} else if (this.props.context == 'queue'){
var type = (track.added_from ? helpers.uriType(track.added_from) : null)
if (track.added_from && track.added_by){
var added = <span>{track.added_by} <span className="grey-text"> (from <Link to={global.baseURL+type+'/'+track.added_from}>{type}</Link>)</span></span>
} else if (track.added_from){
var added = <span className="grey-text"> (from <Link to={global.baseURL+type+'/'+track.added_from}>{type}</Link>)</span>
} else if (track.added_by){
var added = track.added_by
} else {
var added = '-'
}
default:
var track_columns = (
<span>
<span className="col name">
@ -84,12 +97,35 @@ export default class Track extends React.Component{
<span className="col album">
{album}
</span>
<span className="col added">
{added}
</span>
<span className="col duration">
{ track.duration_ms ? <Dater type="length" data={track.duration_ms} /> : null }
{ track.length ? <Dater type="length" data={track.length} /> : null }
</span>
</span>
)
} else {
var track_columns = (
<span>
<span className="col name">
{ track.name ? track.name : <span className="grey-text">{track.uri}</span> }
</span>
<span className="col artists">
{ track.artists ? <ArtistSentence artists={track.artists} /> : '-' }
</span>
<span className="col album">
{album}
</span>
<span className="col duration">
{ track.duration_ms ? <Dater type="length" data={track.duration_ms} /> : null }
{ track.length ? <Dater type="length" data={track.length} /> : null }
</span>
</span>
)
}
return (

View File

@ -240,7 +240,7 @@ class TrackList extends React.Component{
for( var i = 0; i < tracks.length; i++ ){
uris.push( tracks[i].uri )
}
return this.props.mopidyActions.playURIs( uris )
return this.props.mopidyActions.playURIs( uris, this.props.uri )
}
removeTracks(){
@ -269,6 +269,18 @@ class TrackList extends React.Component{
)
break
case 'queue':
return (
<div className="list-item header track">
<span className="col name">Name</span>
<span className="col artists">Artists</span>
<span className="col album">Album</span>
<span className="col added">Added by</span>
<span className="col duration">Length</span>
</div>
)
break
default:
return (
<div className="list-item header track">
@ -295,6 +307,7 @@ class TrackList extends React.Component{
show_source_icon={ this.props.show_source_icon }
key={track.key}
track={track}
context={this.props.context}
handleDoubleClick={ e => self.handleDoubleClick(e, index)}
handleMouseUp={ e => self.handleMouseUp(e, index)}
handleMouseDown={ e => self.handleMouseDown(e, index)}

View File

@ -49,10 +49,11 @@ export function changeTrack( tlid ){
}
}
export function playURIs( uris ){
export function playURIs( uris, from_uri = null ){
return {
type: 'MOPIDY_PLAY_URIS',
uris: uris
uris: uris,
from_uri: from_uri
}
}
@ -65,15 +66,12 @@ export function enqueueURIsNext( uris, from_uri = null ){
}
}
// TODO: Create separate action type for this, rather than using _INSTRUCT
export function enqueueURIs( uris, from_uri = null, at_position = false ){
if( typeof(uris) !== 'object' ) uris = [uris];
var value = { uris: uris };
if( at_position ) value.at_position = at_position;
return {
type: 'MOPIDY_INSTRUCT',
call: 'tracklist.add',
value: value
type: 'MOPIDY_ENQUEUE_URIS',
uris: uris,
at_position: at_position,
from_uri: from_uri
}
}

View File

@ -233,6 +233,22 @@ const MopidyMiddleware = (function(){
})
break;
case 'MOPIDY_ENQUEUE_URIS':
var value = { uris: action.uris }
if (action.at_position){
value.at_position = action.at_position
}
instruct( socket, store, 'tracklist.add', value )
.then( response => {
var tlids = []
for (var i = 0; i < response.length; i++){
tlids.push(response[i].tlid)
}
store.dispatch( pusherActions.addQueueMetadata(tlids, action.from_uri) )
})
break
case 'MOPIDY_ENQUEUE_URIS_NEXT':
var current_track = store.getState().ui.current_track
@ -273,16 +289,22 @@ const MopidyMiddleware = (function(){
.then( response => {
if( !response || response.length <= 0 ){
store.dispatch( uiActions.createNotification('Could not add URI(s) to tracklist', 'error') )
store.dispatch( uiActions.createNotification('Failed to load URI(s)', 'bad') )
}else{
// play it
store.dispatch( mopidyActions.changeTrack( response[0].tlid ) );
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) )
}
// add the rest of our uris (if any)
action.uris.shift();
if( action.uris.length > 0 ){
store.dispatch( mopidyActions.enqueueURIs( action.uris, 1 ) )
store.dispatch( mopidyActions.enqueueURIs( action.uris, action.from_uri, 1 ) )
}
})
break;

View File

@ -154,6 +154,12 @@ const PusherMiddleware = (function(){
store.dispatch({ type: 'RADIO', data: response.data })
}
)
request({ action: 'get_queue_metadata'})
.then(
response => {
store.dispatch({ type: 'QUEUE_METADATA', queue_metadata: response.data.queue_metadata })
}
)
return next(action);
break;
@ -171,7 +177,7 @@ const PusherMiddleware = (function(){
break;
case 'PUSHER_ADD_QUEUE_METADATA':
request({ action: 'add_queue_metadata', tlids: action.tlids, from_uri: action.from_uri })
request({ action: 'add_queue_metadata', tlids: action.tlids, added_from: action.from_uri })
.then(
response => {
store.dispatch({ type: 'QUEUE_METADATA', queue_metadata: response.data.queue_metadata })

View File

@ -81,12 +81,23 @@ export default function reducer(ui = {}, action){
var tracklist = []
for( var i = 0; i < action.data.length; i++ ){
var tltrack = action.data[i]
// load our metadata (if we have any for that tlid)
if (typeof(ui.queue_metadata) !== 'undefined' && typeof(ui.queue_metadata['tlid_'+tltrack.tlid]) !== 'undefined'){
var metadata = ui.queue_metadata['tlid_'+tltrack.tlid]
} else {
var metadata = {}
}
var track = Object.assign(
{},
action.data[i].track,
tltrack.track,
metadata,
{
tlid: action.data[i].tlid,
playing: ( ui.current_track && action.data[i].tlid == ui.current_track.tlid )
tlid: tltrack.tlid,
playing: ( ui.current_track && tltrack.tlid == ui.current_track.tlid )
})
tracklist.push( track )
}
@ -120,8 +131,8 @@ export default function reducer(ui = {}, action){
});
case 'QUEUE_METADATA':
console.log(action)
return Object.assign({}, ui, { queue_metadata: action.queue_metadata })
console.log(action);
return Object.assign({}, ui, { queue_metadata: action.queue_metadata });
case 'RADIO':
case 'START_RADIO':

View File

@ -77,7 +77,7 @@ class Album extends React.Component{
}
play(){
this.props.mopidyActions.playURIs([this.props.params.uri])
this.props.mopidyActions.playURIs([this.props.params.uri], this.props.params.uri)
}
render(){

View File

@ -157,7 +157,7 @@ class Artist extends React.Component{
<div className={related_artists.length > 0 ? "col w70" : "col w100"}>
<h4 className="left-padding">Top tracks</h4>
<div className="list-wrapper">
{ this.props.artist.tracks ? <TrackList uris={this.props.params.uri} tracks={this.props.artist.tracks} /> : null }
{ this.props.artist.tracks ? <TrackList uri={this.props.params.uri} tracks={this.props.artist.tracks} /> : null }
</div>
</div>

View File

@ -59,7 +59,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.mopidyActions.playURIs([this.props.playlist.uri], this.props.params.uri)
}
follow(){

View File

@ -82,8 +82,8 @@ class Queue extends React.Component{
<section className="list-wrapper">
<TrackList
show_source_icon={true}
context="queue-track"
tracks={this.props.current_tracklist}
context="queue"
tracks={this.props.current_tracklist}
removeTracks={ tracks => this.removeTracks( tracks ) }
playTracks={ tracks => this.playTracks( tracks ) }
playTrack={ track => this.playTrack( track ) }

View File

@ -161,4 +161,15 @@
}
}
}
.queue.track-list {
.list-item {
.col{
&.name,
&.artists,
&.album { width: 25%; }
&.added { width: 20%; }
}
}
}
}