diff --git a/src/js/components/AlbumGrid.js b/src/js/components/AlbumGrid.js index 63184cf9..e4c27c3b 100755 --- a/src/js/components/AlbumGrid.js +++ b/src/js/components/AlbumGrid.js @@ -22,9 +22,12 @@ class AlbumGrid extends React.Component{ } } - handleContextMenu(e,uri){ + handleContextMenu(e,item){ e.preventDefault() - var data = { uris: [uri] } + var data = { + uris: [item.uri], + item: item + } this.props.uiActions.showContextMenu( e, data, 'album', 'click' ) } @@ -41,7 +44,7 @@ class AlbumGrid extends React.Component{
this.handleClick(e,global.baseURL+'album/'+album.uri) } - onContextMenu={e => this.handleContextMenu(e,album.uri)}> + onContextMenu={e => this.handleContextMenu(e,album)}>
{ album.name }
diff --git a/src/js/components/ArtistGrid.js b/src/js/components/ArtistGrid.js index 4747183e..9088c1f2 100755 --- a/src/js/components/ArtistGrid.js +++ b/src/js/components/ArtistGrid.js @@ -14,9 +14,12 @@ class ArtistGrid extends React.Component{ super(props); } - handleContextMenu(e,uri){ + handleContextMenu(e,item){ e.preventDefault() - var data = { uris: [uri] } + var data = { + uris: [item.uri], + item: item + } this.props.uiActions.showContextMenu( e, data, 'artist', 'click' ) } @@ -34,7 +37,7 @@ class ArtistGrid extends React.Component{ className="grid-item" to={global.baseURL+'artist/'+artist.uri} key={index} - onContextMenu={e => this.handleContextMenu(e,artist.uri)}> + onContextMenu={e => this.handleContextMenu(e,artist)}>
{ artist.name }
diff --git a/src/js/components/ContextMenu.js b/src/js/components/ContextMenu.js index 4a728f5c..2b940d56 100755 --- a/src/js/components/ContextMenu.js +++ b/src/js/components/ContextMenu.js @@ -1,5 +1,6 @@ import React, { PropTypes } from 'react' +import { Link } from 'react-router' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import FontAwesome from 'react-fontawesome' @@ -7,6 +8,7 @@ import FontAwesome from 'react-fontawesome' import TrackList from './TrackList' import * as helpers from '../helpers' import * as uiActions from '../services/ui/actions' +import * as pusherActions from '../services/pusher/actions' import * as mopidyActions from '../services/mopidy/actions' import * as spotifyActions from '../services/spotify/actions' @@ -86,6 +88,11 @@ class ContextMenu extends React.Component{ this.props.uiActions.hideContextMenu(); } + startRadio(){ + this.props.pusherActions.startRadio(this.props.context_menu.data.uris) + this.props.uiActions.hideContextMenu(); + } + copyURIs(e){ var temp = $(""); $("body").append(temp); @@ -126,7 +133,7 @@ class ContextMenu extends React.Component{ ) } - getItems(trigger){ + getItems(){ switch (this.props.context_menu.context) { case 'queue': @@ -138,22 +145,12 @@ class ContextMenu extends React.Component{ ] break - case 'editable-playlist': - var items = [ - { handleClick: 'playURIs', label: 'Play', icon: 'play' }, - { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' }, - { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' }, - { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true }, - { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' }, - { handleClick: 'removeFromPlaylist', label: 'Remove', icon: 'trash' } - ] - break - case 'album': var items = [ { handleClick: 'playURIs', label: 'Play', icon: 'play' }, { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' }, { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' }, + { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' }, { handleClick: 'copyURIs', label: 'Copy URI', icon: 'copy' } ] break @@ -174,12 +171,25 @@ class ContextMenu extends React.Component{ ] break + case 'editable-playlist-track': + var items = [ + { handleClick: 'playURIs', label: 'Play', icon: 'play' }, + { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' }, + { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' }, + { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true }, + { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' }, + { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' }, + { handleClick: 'removeFromPlaylist', label: 'Remove', icon: 'trash' } + ] + break + default: var items = [ { handleClick: 'playURIs', label: 'Play', icon: 'play' }, { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' }, { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' }, { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true }, + { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' }, { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' } ] break @@ -189,31 +199,23 @@ class ContextMenu extends React.Component{ } renderTitle(){ - var style = {} var item = this.props.context_menu.data.item - var image = null + var style = null if (item && item.images){ - image = helpers.sizedImages(item.images).medium + style = { + backgroundImage: 'url('+helpers.sizedImages(item.images).medium+')' + } } return ( -
- {image ? : null} - {this.props.context_menu.data.item.name} -
+ + {style ?
: null} +
{item.name}
+ ) } - renderItems(trigger){ - var items = this.getItems(trigger) - - var closeItem = ( - - this.closeAndDeselectTracks(e) }> - - Cancel - - - ) + renderItems(){ + var items = this.getItems() return (
@@ -222,7 +224,7 @@ class ContextMenu extends React.Component{ if( item.playlists ){ return ( - this[item.handleClick](e) }> + this[item.handleClick](e)}> { item.label } @@ -233,7 +235,7 @@ class ContextMenu extends React.Component{ }else{ return ( - this[item.handleClick](e) }> + this[item.handleClick](e)}> { item.label } @@ -242,7 +244,6 @@ class ContextMenu extends React.Component{ } }) } - { trigger == 'touch' ? closeItem : null }
) } @@ -277,7 +278,7 @@ class ContextMenu extends React.Component{ return (
- {this.renderTitle()} + {this.props.context_menu.data.item ? this.renderTitle() : null} {this.renderItems(trigger)}
); @@ -298,6 +299,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = (dispatch) => { return { uiActions: bindActionCreators(uiActions, dispatch), + pusherActions: bindActionCreators(pusherActions, dispatch), spotifyActions: bindActionCreators(spotifyActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch) } diff --git a/src/js/components/GridSlider.js b/src/js/components/GridSlider.js index 79d85320..0098b95c 100755 --- a/src/js/components/GridSlider.js +++ b/src/js/components/GridSlider.js @@ -1,9 +1,16 @@ import React, { PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStore, bindActionCreators } from 'redux' +import { Link } from 'react-router' import FontAwesome from 'react-fontawesome' -import GridItem from './GridItem' -export default class GridSlider extends React.Component{ +import ArtistSentence from './ArtistSentence' +import Thumbnail from './Thumbnail' + +import * as uiActions from '../services/ui/actions' + +class GridSlider extends React.Component{ constructor(props) { super(props) @@ -15,6 +22,21 @@ export default class GridSlider extends React.Component{ } } + handleClick(e,link){ + if( e.target.tagName.toLowerCase() !== 'a' ){ + hashHistory.push(link) + } + } + + handleContextMenu(e,item){ + e.preventDefault() + var data = { + uris: [item.uri], + item: item + } + this.props.uiActions.showContextMenu( e, data, 'album', 'click' ) + } + next(){ if (this.state.page >= this._pagelimit) return false this.setState({ page: this.state.page + 1 }) @@ -47,8 +69,19 @@ export default class GridSlider extends React.Component{ { this.props.tracks.map( (track, index) => { - var item = Object.assign({}, track.album, { artists: track.artists }) - return + var album = Object.assign({}, track.album, { artists: track.artists }) + return ( +
this.handleClick(e,global.baseURL+'album/'+album.uri) } + onContextMenu={e => this.handleContextMenu(e,album)}> + +
{ album.name }
+
+ { album.artists ? : - } +
+
+ ) } ) } @@ -61,3 +94,15 @@ export default class GridSlider extends React.Component{ } } +const mapStateToProps = (state, ownProps) => { + return {} +} + +const mapDispatchToProps = (dispatch) => { + return { + uiActions: bindActionCreators(uiActions, dispatch) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(GridSlider) + diff --git a/src/js/components/List.js b/src/js/components/List.js index 88f2de74..43f5c8cb 100755 --- a/src/js/components/List.js +++ b/src/js/components/List.js @@ -25,10 +25,13 @@ class List extends React.Component{ } } - handleContextMenu(e,uri){ + handleContextMenu(e,item){ e.preventDefault() - var data = { uris: [uri] } - this.props.uiActions.showContextMenu(e, data, helpers.uriType(uri), 'click') + var data = { + uris: [item.uri], + item: item + } + this.props.uiActions.showContextMenu(e, data, helpers.uriType(item.uri), 'click') } renderHeader(){ @@ -82,7 +85,7 @@ class List extends React.Component{ return (
this.handleClick(e, row.uri)} - onContextMenu={e => this.handleContextMenu(e,row.uri)} + onContextMenu={e => this.handleContextMenu(e,row)} className={className} key={row_index}> { diff --git a/src/js/components/Sidebar.js b/src/js/components/Sidebar.js index 0f8af507..2115136f 100755 --- a/src/js/components/Sidebar.js +++ b/src/js/components/Sidebar.js @@ -39,7 +39,7 @@ class Sidebar extends React.Component{
Discover - + Discover diff --git a/src/js/services/pusher/middleware.js b/src/js/services/pusher/middleware.js index 588f2372..eb8082fe 100755 --- a/src/js/services/pusher/middleware.js +++ b/src/js/services/pusher/middleware.js @@ -214,7 +214,7 @@ const PusherMiddleware = (function(){ }) .then( response => { - uiActions.createNotification('Starting radio...') + store.dispatch(uiActions.createNotification('Starting radio...')) } ) @@ -252,11 +252,11 @@ const PusherMiddleware = (function(){ }) .then( response => { - uiActions.createNotification('Stopping radio') + store.dispatch(uiActions.createNotification('Stopping radio')) } ) - store.dispatch( uiActions.createNotification('Stopping radio') ) + store.dispatch(uiActions.createNotification('Stopping radio')) var data = { action: 'stop_radio', seed_artists: [], diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index d5431a51..c71d15c8 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -532,10 +532,9 @@ export function resolveRadioSeeds( radio ){ // add to our list of async requests requests.push( - sendRequest( dispatch, getState, 'tracks/'+ track_ids ) + sendRequest( dispatch, getState, 'tracks?ids='+ track_ids ) .then( response => { - if (!(response instanceof Array)) response = [response] - Object.assign(resolved_seeds.seed_tracks, response); + Object.assign(resolved_seeds.seed_tracks, response.tracks); }) ) } diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index 78214047..6aca393c 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -94,7 +94,7 @@ const SpotifyMiddleware = (function(){ // only resolve if radio is enabled if( action.data.radio.enabled ){ - store.dispatch( spotifyActions.resolveRadioSeeds( action.data.radio ) ) + store.dispatch(spotifyActions.resolveRadioSeeds(action.data.radio)) } break diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index c94477ed..91228e00 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -153,7 +153,7 @@ class Playlist extends React.Component{
- { this.props.playlist.tracks ? this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null } + { this.props.playlist.tracks ? this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null } this.loadMore() }/>
diff --git a/src/js/views/Queue.js b/src/js/views/Queue.js index db32cb7f..7c7197d5 100755 --- a/src/js/views/Queue.js +++ b/src/js/views/Queue.js @@ -67,7 +67,7 @@ class Queue extends React.Component{ } } if (this.props.radio.seed_genres.length > 0) seed_sentence =this.props.radio.seed_artists.length+' genres' - if (this.props.radio.seed_tracks.length > 0) seed_sentence =this.props.radio.seed_artists.length+' tracks' + if (this.props.radio.seed_tracks.length > 0) seed_sentence =this.props.radio.seed_tracks.length+' tracks' return (
diff --git a/src/scss/components/_context-menu.scss b/src/scss/components/_context-menu.scss index 31142f8d..c3bed4a3 100755 --- a/src/scss/components/_context-menu.scss +++ b/src/scss/components/_context-menu.scss @@ -25,21 +25,38 @@ cursor: pointer; display: block; padding: 8px 12px; - width: 100%; + width: 140px; font-weight: bold; box-sizing: border-box; position: relative; overflow: hidden; + text-decoration: none; + background: $darkest_grey; - img { + .background { @include blur(5px); background-size: cover; - background-position: 50% 0%; - opacity: 0.2; + background-position: 50% 20%; + opacity: 0.5; position: absolute; - top: 0; - left: 0; - right: 0; + top: -10px; + left: -10px; + bottom: -10px; + right: -10px; + z-index: 1; + } + + .text { + @include one_line_text(); + position: relative; + z-index: 2; + color: #FFFFFF; + } + + &:hover{ + .background { + opacity: 0.7; + } } } @@ -87,7 +104,7 @@ opacity: 0.5; } - &:not(:first-child) .menu-item { + .menu-item { border-top: 1px solid lighten($dark_grey, 8%); }