diff --git a/mopidy_iris/core.py b/mopidy_iris/core.py index d5719948..2b030442 100755 --- a/mopidy_iris/core.py +++ b/mopidy_iris/core.py @@ -260,9 +260,11 @@ class IrisCore(object): # no uris means we can't play radio if not uris: + self.radio['enabled'] = 0 return { 'status': 0, - 'message': 'No recommendations found' + 'message': 'No recommendations found', + 'radio': self.radio } # if we got recommendations @@ -279,6 +281,31 @@ class IrisCore(object): return self.get_radio({}) + def update_radio(self, data): + self.radio = data + self.radio['enabled'] = 1; + + uris = self.load_more_tracks() + + # no uris means we can't play radio + if not uris: + self.radio['enabled'] = 0 + return { + 'status': 0, + 'message': 'No recommendations found', + 'radio': self.radio + } + + # if we got recommendations + else: + self.core.tracklist.add( uris = uris ) + self.broadcast({ + 'type': 'radio_updated', + 'radio': self.radio + }) + + return self.get_radio({}) + def stop_radio(self, data): self.radio = { diff --git a/src/assets/radio-overlay.png b/src/assets/radio-overlay.png new file mode 100755 index 00000000..2213b532 Binary files /dev/null and b/src/assets/radio-overlay.png differ diff --git a/src/js/components/FullPlayer.js b/src/js/components/FullPlayer.js index caaf8573..4b5f6f96 100755 --- a/src/js/components/FullPlayer.js +++ b/src/js/components/FullPlayer.js @@ -69,6 +69,7 @@ class FullPlayer extends React.Component{ !this.props.current_track.album.images ){ return ( + {this.props.radio_enabled ? : null} ) @@ -78,6 +79,7 @@ class FullPlayer extends React.Component{ if( this.props.current_track.album.uri ) link = '/album/'+this.props.current_track.album.uri return ( this.handleContextMenu(e,this.props.current_track.album)}> + {this.props.radio_enabled ? : null} ) @@ -90,8 +92,10 @@ class FullPlayer extends React.Component{ { this.renderArtwork() }
-
{ this.props.current_track ? this.props.current_track.name : - }
- { this.props.current_track ? : } +
+ {this.props.current_track ? this.props.current_track.name : -} +
+ {this.props.current_track ? : }
@@ -135,6 +139,7 @@ class FullPlayer extends React.Component{ const mapStateToProps = (state, ownProps) => { return { + radio_enabled: (state.ui.radio && state.ui.radio.enabled ? true : false), current_track: state.ui.current_track, play_state: state.mopidy.play_state, time_position: state.mopidy.time_position, diff --git a/src/js/components/Modal/EditRadioModal.js b/src/js/components/Modal/EditRadioModal.js index 1b60aab0..d14a4d6a 100755 --- a/src/js/components/Modal/EditRadioModal.js +++ b/src/js/components/Modal/EditRadioModal.js @@ -12,7 +12,8 @@ export default class EditRadioModal extends React.Component{ this.state = { enabled: false, seeds: [], - uri: '' + uri: '', + error_message: null } } @@ -24,26 +25,39 @@ export default class EditRadioModal extends React.Component{ this.props.spotifyActions.resolveRadioSeeds(this.props.radio) } - handleSubmit(e){ - if (this.state.enabled){ - this.props.pusherActions.startRadio(this.state.seeds) - }else{ - this.props.pusherActions.stopRadio() - } + handleStart(e){ + e.preventDefault() + this.props.pusherActions.startRadio(this.state.seeds) + this.props.uiActions.closeModal() + } + + handleUpdate(e){ + e.preventDefault() + this.props.pusherActions.updateRadio(this.state.seeds) + this.props.uiActions.closeModal() + } + + handleStop(e){ + e.preventDefault() + this.props.pusherActions.stopRadio() this.props.uiActions.closeModal() } addSeed(){ - if (this.state.uri == '') return null + if (this.state.uri == ''){ + this.setState({error_message: 'Cannot be empty'}) + return null + } var seeds = Object.assign([],this.state.seeds) var uris = this.state.uri.split(',') for (var i = 0; i < uris.length; i++){ - if (seeds.indexOf(uris[i]) <= -1){ - seeds.push(uris[i]) + if (seeds.indexOf(uris[i]) > -1){ + this.setState({error_message: 'URI already added'}) } else { - this.props.uiActions.createNotification(uris[i]+' already added','bad') + seeds.push(uris[i]) + this.setState({error_message: null}) } } @@ -71,8 +85,8 @@ export default class EditRadioModal extends React.Component{ for (var i = 0; i < this.state.seeds.length; i++){ var uri = this.state.seeds[i] if (uri){ - if (helpers.uriType(uri) == 'artist' && this.props.artists){ - if (this.props.artists.hasOwnProperty(uri)){ + if (helpers.uriType(uri) == 'artist'){ + if (this.props.artists && this.props.artists.hasOwnProperty(uri)){ seeds.push(this.props.artists[uri]) } else { seeds.push({ @@ -81,8 +95,8 @@ export default class EditRadioModal extends React.Component{ uri: uri }) } - } else if (helpers.uriType(uri) == 'track' && this.props.tracks){ - if (this.props.tracks.hasOwnProperty(uri)){ + } else if (helpers.uriType(uri) == 'track'){ + if (this.props.tracks && this.props.tracks.hasOwnProperty(uri)){ seeds.push(this.props.tracks[uri]) } else { seeds.push({ @@ -105,7 +119,9 @@ export default class EditRadioModal extends React.Component{
{seed.unresolved ? {seed.uri} : {seed.name} }  ({seed.type}) - this.removeSeed(seed.uri)} /> +
) }) @@ -115,41 +131,29 @@ export default class EditRadioModal extends React.Component{ ) } - renderAddSeeds(){ - return ( -
- this.setState({uri: e.target.value})} - value={this.state.uri} /> - -
- ) - } - render(){ return (
-

Edit radio

+

Manage radio

-
this.handleSubmit(e)}> -
- + + {this.renderSeeds()} + +
+ this.setState({uri: e.target.value, error_message: null})} + value={this.state.uri} /> + + {this.state.error_message ? {this.state.error_message} : null}
- {this.state.enabled ? this.renderSeeds() : null} - {this.state.enabled ? this.renderAddSeeds() : null} -
- + {this.state.enabled ? : null} + {this.state.enabled ? : }
diff --git a/src/js/services/pusher/actions.js b/src/js/services/pusher/actions.js index 6e9b6eb1..2db1d776 100755 --- a/src/js/services/pusher/actions.js +++ b/src/js/services/pusher/actions.js @@ -76,6 +76,13 @@ export function startRadio( uris ){ } } +export function updateRadio( uris ){ + return { + type: 'PUSHER_UPDATE_RADIO', + uris: uris + } +} + export function stopRadio(){ return { type: 'PUSHER_STOP_RADIO' diff --git a/src/js/services/pusher/middleware.js b/src/js/services/pusher/middleware.js index a7d4563e..f231f8bf 100755 --- a/src/js/services/pusher/middleware.js +++ b/src/js/services/pusher/middleware.js @@ -243,7 +243,16 @@ const PusherMiddleware = (function(){ break case 'PUSHER_START_RADIO': - store.dispatch(uiActions.createNotification('Starting radio...')) + case 'PUSHER_UPDATE_RADIO': + if (action.type == 'PUSHER_UPDATE_RADIO'){ + var method = 'update_radio' + var process_text = 'Updating radio' + } else { + var method = 'start_radio' + var process_text = 'Starting radio' + } + + store.dispatch(uiActions.startProcess('PUSHER_RADIO', process_text)) var data = { seed_artists: [], @@ -264,19 +273,11 @@ const PusherMiddleware = (function(){ break; } } - - // we don't need to wait for response, as change will be broadcast - request(store, 'start_radio', data) - break - case 'PUSHER_RADIO_STARTED': - var data = { - type: 'browser_notification', - title: 'Radio', - body: 'Radio mode started', - icon: (store.getState().ui.current_track ? helpers.getTrackIcon( store.getState().ui.current_track ) : false) - } - store.dispatch( pusherActions.deliverBroadcast(data) ) + request(store, method, data) + .then(response => { + store.dispatch(uiActions.stopProcess('PUSHER_RADIO')) + }) break case 'PUSHER_STOP_RADIO': @@ -292,22 +293,11 @@ const PusherMiddleware = (function(){ request(store, 'stop_radio', data) break - case 'PUSHER_RADIO_STOPPED': - var data = { - type: 'browser_notification', - title: 'Radio', - body: 'Radio mode stopped', - icon: (store.getState().ui.current_track ? helpers.getTrackIcon( store.getState().ui.current_track ) : false) - } - store.dispatch( pusherActions.deliverBroadcast(data) ) - break - case 'PUSHER_BROWSER_NOTIFICATION': store.dispatch(uiActions.createBrowserNotification(action)) break case 'PUSHER_RESTART': - // Hard reload. This doesn't strictly clear the cache, but our compiler's // cache buster should handle that window.location.reload(true); diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 6b334bec..4fd0cb95 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -528,13 +528,16 @@ export function resolveRadioSeeds( radio ){ artist_ids += helpers.getFromUri('artistid', radio.seed_artists[i]) } - sendRequest( dispatch, getState, 'artists/'+ artist_ids ) + sendRequest( dispatch, getState, 'artists?ids='+ artist_ids ) .then( response => { - if (!(response instanceof Array)) response = [response] - dispatch({ - type: 'ARTISTS_LOADED', - artists: response - }) + if (response && response.artists){ + dispatch({ + type: 'ARTISTS_LOADED', + artists: response.artists + }) + } else { + console.error('No Spotify artists returned', artist_ids) + } }) } diff --git a/src/js/views/Queue.js b/src/js/views/Queue.js index b28302cd..b1a589b4 100755 --- a/src/js/views/Queue.js +++ b/src/js/views/Queue.js @@ -62,6 +62,7 @@ class Queue extends React.Component{