Files
Iris/src/js/components/ContextMenu.js

799 lines
23 KiB
JavaScript
Raw Normal View History

2016-10-27 10:02:12 +13:00
import React, { PropTypes } from 'react'
2017-02-27 08:44:02 +13:00
import { Link, hashHistory } from 'react-router'
2016-10-27 10:02:12 +13:00
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
2016-11-12 16:36:36 +13:00
import FontAwesome from 'react-fontawesome'
2016-10-27 10:02:12 +13:00
import * as helpers from '../helpers'
2017-08-02 21:11:22 +12:00
import * as coreActions from '../services/core/actions'
2016-10-27 10:02:12 +13:00
import * as uiActions from '../services/ui/actions'
import * as pusherActions from '../services/pusher/actions'
2016-10-27 10:02:12 +13:00
import * as mopidyActions from '../services/mopidy/actions'
import * as lastfmActions from '../services/lastfm/actions'
2016-10-27 10:02:12 +13:00
import * as spotifyActions from '../services/spotify/actions'
2017-08-02 21:11:22 +12:00
import TrackList from './TrackList'
2016-10-27 10:02:12 +13:00
class ContextMenu extends React.Component{
2017-10-10 13:05:28 +13:00
constructor(props){
2017-02-28 20:58:15 +13:00
super(props)
this.state = {
submenu_expanded: false
2017-02-28 20:58:15 +13:00
}
this.handleScroll = this.handleScroll.bind(this);
2017-11-20 15:49:52 +13:00
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleTouchStart = this.handleTouchStart.bind(this);
}
2016-12-14 16:41:05 +13:00
2017-02-28 20:58:15 +13:00
componentDidMount(){
window.addEventListener("scroll", this.handleScroll, false);
2017-11-20 15:49:52 +13:00
window.addEventListener("mousedown", this.handleMouseDown, false);
window.addEventListener("touchstart", this.handleTouchStart, false);
}
componentWillUnmount(){
window.removeEventListener("scroll", this.handleScroll, false);
2017-11-20 15:49:52 +13:00
window.removeEventListener("mousedown", this.handleMouseDown, false);
window.removeEventListener("touchstart", this.handleTouchStart, false);
}
2017-10-10 13:05:28 +13:00
componentWillReceiveProps(nextProps){
2017-03-10 22:35:11 +13:00
2017-02-28 20:58:15 +13:00
// if we've been given a menu object (ie activated) when we didn't have one prior
if (nextProps.menu && !this.props.menu){
this.setState({ submenu_expanded: false })
2017-03-13 05:39:12 +13:00
$('body').addClass('context-menu-open')
var context = this.getContext(nextProps);
2017-02-28 20:58:15 +13:00
// if we're able to be in the library, run a check
if (nextProps.spotify_authorized && context.source == 'spotify'){
switch (nextProps.menu.context){
case 'artist':
case 'album':
case 'playlist':
this.props.spotifyActions.following(nextProps.menu.items[0].uri)
break
}
}
// if we're able to be in the LastFM library, run a check
if (nextProps.lastfm_authorized && context.is_track && context.items_count == 1){
if (nextProps.menu.items[0].uri && this.props.tracks[nextProps.menu.items[0].uri] !== undefined && this.props.tracks[nextProps.menu.items[0].uri].userloved === undefined){
this.props.lastfmActions.getTrack(nextProps.menu.items[0].uri);
}
}
2017-02-28 20:58:15 +13:00
// we DID have one prior, and now we don't
} else if (this.props.menu && !nextProps.menu){
$('body').removeClass('context-menu-open')
}
}
2017-02-27 08:44:02 +13:00
handleScroll(e){
if (this.props.menu){
this.props.uiActions.hideContextMenu();
2017-02-27 08:44:02 +13:00
}
2016-12-14 16:41:05 +13:00
}
2017-11-20 15:49:52 +13:00
handleMouseDown(e){
// if we click (touch or mouse) outside of the context menu or context menu trigger, kill it
if ($(e.target).closest('.context-menu').length <= 0 && $(e.target).closest('.context-menu-trigger').length <= 0){
this.props.uiActions.hideContextMenu();
}
}
handleTouchStart(e){
// if we click (touch or mouse) outside of the context menu or context menu trigger, kill it
if ($(e.target).closest('.context-menu').length <= 0 && $(e.target).closest('.context-menu-trigger').length <= 0){
this.props.uiActions.hideContextMenu();
2017-02-27 08:44:02 +13:00
}
2016-12-14 16:41:05 +13:00
}
getContext(props = this.props){
var context = {
name: null,
nice_name: 'Unknown',
is_track: false
}
if (props.menu && props.menu.context){
context.name = props.menu.context;
context.nice_name = props.menu.context;
2017-03-13 05:39:12 +13:00
// handle ugly labels
switch (props.menu.context){
case 'playlist':
case 'editable-playlist':
context.nice_name = 'playlist';
2018-01-11 16:46:57 +13:00
break;
case 'track':
case 'queue-track':
case 'playlist-track':
case 'editable-playlist-track':
context.nice_name = 'track';
context.is_track = true;
2018-01-11 16:46:57 +13:00
break;
}
2017-03-13 05:39:12 +13:00
// Consider the object(s) themselves
// We can only really accommodate the first item. The only instances where
// there is multiple is tracklists, when they're all of the same source (except search?)
if (props.menu.items && props.menu.items.length > 0){
var item = props.menu.items[0]
context.item = item;
context.items_count = props.menu.items.length;
context.source = helpers.uriSource(item.uri);
context.type = helpers.uriType(item.uri);
context.in_library = this.inLibrary(item);
context.is_loved = this.isLoved(item);
2017-03-13 05:39:12 +13:00
}
}
return context
}
2017-03-13 05:39:12 +13:00
inLibrary(item = null){
if (!item){
2018-01-11 16:46:57 +13:00
return false;
2017-03-10 22:35:11 +13:00
}
2017-03-13 05:39:12 +13:00
switch (helpers.uriType(item.uri)){
2017-03-10 22:35:11 +13:00
case 'artist':
2018-01-11 16:46:57 +13:00
return (this.props.spotify_library_artists && this.props.spotify_library_artists.indexOf(item.uri) > -1);
break;
2017-03-10 22:35:11 +13:00
case 'album':
2018-01-11 16:46:57 +13:00
return (this.props.spotify_library_albums && this.props.spotify_library_albums.indexOf(item.uri) > -1);
break;
2017-03-10 22:35:11 +13:00
case 'playlist':
2018-01-11 16:46:57 +13:00
return (this.props.spotify_library_playlists && this.props.spotify_library_playlists.indexOf(item.uri) > -1);
break;
2017-03-10 22:35:11 +13:00
}
2018-01-11 16:46:57 +13:00
return false;
2017-03-10 22:35:11 +13:00
}
/**
* TODO: Currently the select track keys are the only details available. We need
* the actual track object reference (including name and artists) to getTrack from LastFM
**/
isLoved(item = null){
if (!item){
return false
}
if (this.props.tracks[item.uri] === undefined){
return false;
}
var track = this.props.tracks[item.uri];
return (track.userloved !== undefined && track.userloved == "1");
}
canBeInLibrary(){
if (!this.props.spotify_authorized){
return false
}
return (helpers.uriSource(this.props.menu.items[0].uri) == 'spotify')
}
toggleInLibrary(e, in_library){
2017-03-10 22:35:11 +13:00
this.props.uiActions.hideContextMenu()
if (in_library){
this.props.spotifyActions.following(this.props.menu.items[0].uri, 'DELETE')
} else {
this.props.spotifyActions.following(this.props.menu.items[0].uri, 'PUT')
}
}
playQueueItem(e){
this.props.uiActions.hideContextMenu()
var tracks = this.props.menu.items;
2018-01-11 16:46:57 +13:00
this.props.mopidyActions.changeTrack(tracks[0].tlid);
}
removeFromQueue(e){
this.props.uiActions.hideContextMenu()
var tracks = this.props.menu.items;
var tracks_tlids = [];
2017-10-10 13:05:28 +13:00
for(var i = 0; i < tracks.length; i++){
tracks_tlids.push(tracks[i].tlid );
}
2018-01-11 16:46:57 +13:00
this.props.mopidyActions.removeTracks(tracks_tlids);
}
playURIs(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.mopidyActions.playURIs(this.props.menu.uris, this.props.menu.tracklist_uri);
}
playPlaylist(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.mopidyActions.playPlaylist(this.props.menu.uris[0]);
}
playArtistTopTracks(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.spotifyActions.playArtistTopTracks(this.props.menu.uris[0]);
}
addToQueue(e, next = false){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.mopidyActions.enqueueURIs(this.props.menu.uris, this.props.menu.tracklist_uri, next);
}
addTracksToPlaylist(e, playlist_uri){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.coreActions.addTracksToPlaylist(playlist_uri, this.props.menu.uris);
}
toggleLoved(e, is_loved){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
if (is_loved){
2018-01-11 16:46:57 +13:00
this.props.lastfmActions.unloveTrack(this.props.menu.items[0].uri);
} else {
2018-01-11 16:46:57 +13:00
this.props.lastfmActions.loveTrack(this.props.menu.items[0].uri);
}
}
unloveTrack(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.lastfmActions.unloveTrack(this.props.menu.items[0]);
}
removeFromPlaylist(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.coreActions.removeTracksFromPlaylist(this.props.menu.tracklist_uri, this.props.menu.indexes);
2016-10-27 10:02:12 +13:00
}
2017-08-22 20:44:36 +12:00
deletePlaylist(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.coreActions.deletePlaylist(this.props.menu.uris[0]);
2017-08-22 20:44:36 +12:00
}
startRadio(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
this.props.pusherActions.startRadio(this.props.menu.uris);
}
goToRecommendations(e){
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
var uris_string = helpers.arrayOf('uri',this.props.menu.items).join(',');
hashHistory.push(global.baseURL +'discover/recommendations/'+ uris_string );
}
goToArtist(e){
if (!this.props.menu.items || this.props.menu.items.length <= 0 || !this.props.menu.items[0].artists || this.props.menu.items[0].artists.length <= 0){
2018-01-11 16:46:57 +13:00
return null;
} else {
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
hashHistory.push(global.baseURL +'artist/'+ this.props.menu.items[0].artists[0].uri);
}
}
2017-11-23 17:43:29 +13:00
goToAlbum(e){
if (!this.props.menu.items || this.props.menu.items.length <= 0 || !this.props.menu.items[0].album){
2018-01-11 16:46:57 +13:00
return null;
2017-11-23 17:43:29 +13:00
} else {
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
hashHistory.push(global.baseURL +'album/'+ this.props.menu.items[0].album.uri);
2017-11-23 17:43:29 +13:00
}
}
goToUser(e){
if (!this.props.menu.items || this.props.menu.items.length <= 0){
2018-01-11 16:46:57 +13:00
return null;
} else {
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
hashHistory.push(global.baseURL +'user/'+ this.props.menu.items[0].owner.uri);
}
2017-02-27 08:44:02 +13:00
}
goToTrack(e){
if (!this.props.menu.items || this.props.menu.items.length <= 0){
2018-01-11 16:46:57 +13:00
return null;
} else {
2018-01-11 16:46:57 +13:00
this.props.uiActions.hideContextMenu();
hashHistory.push(global.baseURL +'track/'+ encodeURIComponent(this.props.menu.items[0].uri));
}
}
copyURIs(e){
var temp = $("<input>");
$("body").append(temp);
temp.val(this.props.menu.uris.join(',')).select();
document.execCommand("copy");
temp.remove();
2017-10-10 13:05:28 +13:00
this.props.uiActions.createNotification("Copied "+this.props.menu.uris.length+" URIs" )
this.props.uiActions.hideContextMenu()
}
closeAndDeselectTracks(e){
this.props.uiActions.hideContextMenu();
2017-03-13 05:39:12 +13:00
// TODO
}
2016-11-11 23:21:51 +13:00
renderPlaylistSubmenu(){
var playlists = []
2017-01-16 21:49:04 +13:00
for (var uri in this.props.playlists){
2017-10-10 13:05:28 +13:00
if (this.props.playlists[uri].can_edit) playlists.push(this.props.playlists[uri])
2016-11-11 23:21:51 +13:00
}
2017-01-16 21:49:04 +13:00
playlists = helpers.sortItems(playlists, 'name')
2017-08-22 08:38:03 +12:00
var loader = null
if (this.props.processes.SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR && this.props.processes.SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR.status == 'running'){
loader = (
<div className="menu-item-wrapper">
<div className="menu-item mini-loader loading">
<div className="loader"></div>
</div>
</div>
)
}
2017-08-22 20:44:36 +12:00
var list = <span className="menu-item-wrapper"><span className="menu-item grey-text">No writable playlists</span></span>
if (playlists.length > 0){
list = playlists.map(playlist => {
return (
<span className="menu-item-wrapper" key={playlist.uri}>
<a className="menu-item" onClick={e => this.addTracksToPlaylist(e,playlist.uri) }>
<span className="label">{ playlist.name }</span>
</a>
</span>
)
})
}
2016-11-11 23:21:51 +13:00
return (
2017-03-02 08:08:27 +13:00
<div className={this.state.submenu_expanded ? 'submenu expanded' : 'submenu'}>
2017-03-01 08:28:10 +13:00
<span className="menu-item-wrapper">
<a className="menu-item close-submenu" onClick={e => this.setState({submenu_expanded: false})}>
<span className="label">
2017-03-02 08:08:27 +13:00
<FontAwesome name='caret-left' />
&nbsp;&nbsp;
2017-03-02 08:13:04 +13:00
Back
2017-03-01 08:28:10 +13:00
</span>
</a>
</span>
2017-08-22 20:44:36 +12:00
{list}
2017-08-22 08:38:03 +12:00
{loader}
2016-11-11 23:21:51 +13:00
</div>
)
}
2017-01-27 16:13:11 +13:00
renderTitle(){
2017-03-13 05:39:12 +13:00
var context = this.getContext()
2017-03-13 13:17:11 +13:00
if (context.name == 'custom'){
return (
<span className="title">
<div className="background generic"></div>
<div className="text">
{this.props.menu.title}
</div>
</span>
)
2017-03-13 13:17:11 +13:00
}
2017-03-13 05:39:12 +13:00
switch (context.type){
case 'artist':
case 'album':
case 'playlist':
var style = null
2017-03-13 05:39:12 +13:00
if (context.item && context.item.images){
style = {
2017-03-13 05:39:12 +13:00
backgroundImage: 'url('+helpers.sizedImages(context.item.images).medium+')'
}
}
return (
2017-03-13 05:39:12 +13:00
<Link className="title" to={global.baseURL+context.type+'/'+context.item.uri}>
{style ? <div className="background" style={style}></div> : null}
<div className="type">
2017-03-13 05:39:12 +13:00
{context.source}
&nbsp;
2017-03-13 05:39:12 +13:00
{context.nice_name}
</div>
2017-03-13 05:39:12 +13:00
<div className="text">{context.item.name}</div>
</Link>
)
break
default:
return (
<span className="title">
<div className="type">
2017-03-13 05:39:12 +13:00
{context.source}
&nbsp;
2017-03-13 05:39:12 +13:00
{context.nice_name}s
</div>
<div className="text">
2017-03-13 13:17:11 +13:00
{context.items_count} items
</div>
<div className="background generic"></div>
</span>
)
break
2017-01-27 16:13:11 +13:00
}
}
setPlaylistSubmenu(expanded = !this.state.submenu_expanded){
this.setState({submenu_expanded: expanded})
2017-08-13 21:04:59 +12:00
if (expanded){
if (!this.props.spotify_library_playlists_loaded_all){
2017-08-13 21:04:59 +12:00
this.props.spotifyActions.getLibraryPlaylists()
}
if (!this.props.mopidy_library_playlists_loaded_all){
2017-08-13 21:04:59 +12:00
this.props.mopidyActions.getLibraryPlaylists()
}
}
}
renderItems(){
2017-03-13 05:39:12 +13:00
var context = this.getContext()
var play_uris = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.playURIs(e)}>
<span className="label">Play</span>
</a>
</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)}>
<span className="label">Play</span>
</a>
</span>
)
var play_uris_next = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.addToQueue(e, true)}>
<span className="label">Play next</span>
</a>
</span>
)
var play_artist_top_tracks = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.playArtistTopTracks(e)}>
<span className="label">Play top tracks</span>
</a>
</span>
)
var add_to_queue = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.addToQueue(e)}>
<span className="label">Add to queue</span>
</a>
</span>
)
var add_to_playlist = (
<span className="menu-item-wrapper has-submenu">
<a className="menu-item" onClick={e => this.setPlaylistSubmenu()}>
<span className="label">Add to playlist</span>
<FontAwesome className="submenu-icon" name='caret-right' />
</a>
{this.renderPlaylistSubmenu()}
</span>
)
var toggle_in_library = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.toggleInLibrary(e, context.in_library)}>
<span className="label">
2017-03-13 05:39:12 +13:00
{context.in_library ? 'Remove from library' : 'Add to library'}
</span>
</a>
</span>
)
if (!this.props.lastfm_authorized){
var toggle_loved = null;
} else if (helpers.isLoading(this.props.load_queue,['lastfm_track.getInfo'])){
var toggle_loved = (
<span className="menu-item-wrapper">
<a className="menu-item">
<span className="label grey-text">
Love track
</span>
</a>
</span>
)
} else {
var toggle_loved = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.toggleLoved(e, context.is_loved)}>
<span className="label">
{context.is_loved ? 'Unlove' : 'Love'} track
</span>
</a>
</span>
)
}
var go_to_artist = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.goToArtist(e)}>
<span className="label">Go to artist</span>
</a>
</span>
)
2017-11-23 17:43:29 +13:00
var go_to_album = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.goToAlbum(e)}>
<span className="label">Go to album</span>
</a>
</span>
)
var go_to_user = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.goToUser(e)}>
<span className="label">Go to user</span>
</a>
</span>
)
var go_to_track = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.goToTrack(e)}>
<span className="label">Track info</span>
</a>
</span>
)
var go_to_recommendations = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.goToRecommendations(e)}>
<span className="label">Discover similar</span>
</a>
</span>
)
var start_radio = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.startRadio(e)}>
<span className="label">Start radio</span>
</a>
</span>
)
var remove_from_queue = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.removeFromQueue(e)}>
<span className="label">Remove</span>
</a>
</span>
)
var remove_from_playlist = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.removeFromPlaylist(e)}>
<span className="label">Remove</span>
</a>
</span>
)
2017-08-22 20:44:36 +12:00
var delete_playlist = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.deletePlaylist(e)}>
<span className="label">Delete</span>
</a>
</span>
)
var copy_uris = (
<span className="menu-item-wrapper">
<a className="menu-item" onClick={e => this.copyURIs(e)}>
2017-10-26 20:17:07 +13:00
<span className="label">Copy URI{context.items_count > 1 ? 's' : ''}</span>
</a>
</span>
)
2017-03-13 05:39:12 +13:00
switch (context.name){
case 'album':
return (
<div>
{play_uris}
{play_uris_next}
{add_to_queue}
2017-11-23 17:43:29 +13:00
{this.canBeInLibrary() ? <div className="divider" /> : null}
{this.canBeInLibrary() ? toggle_in_library : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
{go_to_artist}
{copy_uris}
</div>
)
break
case 'artist':
return (
<div>
{context.source == 'spotify' ? play_artist_top_tracks : null}
{context.source == 'spotify' ? start_radio : null}
2017-11-23 17:43:29 +13:00
{this.canBeInLibrary() ? <div className="divider" /> : null}
{this.canBeInLibrary() ? toggle_in_library : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
{context.source == 'spotify' ? go_to_recommendations : null}
{copy_uris}
</div>
)
break
case 'playlist':
return (
<div>
{play_playlist}
2017-11-23 17:43:29 +13:00
{this.canBeInLibrary() ? <div className="divider" /> : null}
{this.canBeInLibrary() ? toggle_in_library : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
2017-03-13 05:39:12 +13:00
{context.source == 'spotify' ? go_to_user : null}
{copy_uris}
</div>
)
break
2017-08-22 20:44:36 +12:00
case 'editable-playlist':
return (
<div>
{play_playlist}
2017-11-23 17:43:29 +13:00
{this.canBeInLibrary() ? <div className="divider" /> : null}
{this.canBeInLibrary() ? toggle_in_library : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
2017-08-22 20:44:36 +12:00
{context.source == 'spotify' ? go_to_user : null}
{copy_uris}
2017-10-15 18:53:59 +13:00
<div className="divider" />
2017-08-22 20:44:36 +12:00
{delete_playlist}
</div>
)
break
case 'queue-track':
return (
<div>
2017-10-15 18:53:59 +13:00
{context.items_count == 1 ? play_queue_item : null}
2017-11-23 17:43:29 +13:00
<div className="divider" />
{add_to_playlist}
2017-11-23 17:43:29 +13:00
{toggle_loved}
<div className="divider" />
2017-10-14 20:25:34 +13:00
{context.source == 'spotify' && context.items_count <= 5 ? go_to_recommendations : null}
{context.items_count == 1 ? go_to_track : null}
2017-10-15 18:53:59 +13:00
{copy_uris}
2017-11-23 17:43:29 +13:00
<div className="divider" />
{remove_from_queue}
</div>
)
break
case 'editable-playlist-track':
return (
<div>
{play_uris}
{play_uris_next}
{add_to_queue}
{context.source == 'spotify' && context.items_count == 1 ? start_radio : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
{add_to_playlist}
2017-11-23 17:43:29 +13:00
{toggle_loved}
<div className="divider" />
2017-10-14 20:25:34 +13:00
{context.source == 'spotify' && context.items_count <= 5 ? go_to_recommendations : null}
{context.items_count == 1 ? go_to_track : null}
2017-10-15 18:53:59 +13:00
{copy_uris}
2017-11-23 17:43:29 +13:00
<div className="divider" />
{remove_from_playlist}
</div>
)
break
default:
return (
<div>
{play_uris}
{play_uris_next}
{add_to_queue}
{context.source == 'spotify' && context.items_count == 1 ? start_radio : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
{add_to_playlist}
2017-11-23 17:43:29 +13:00
{toggle_loved}
<div className="divider" />
2017-10-14 20:25:34 +13:00
{context.source == 'spotify' && context.items_count <= 5 ? go_to_recommendations : null}
2017-11-23 17:43:29 +13:00
{context.items_count == 1 ? go_to_album : null}
{context.items_count == 1 ? go_to_track : null}
2017-10-15 18:53:59 +13:00
<div className="divider" />
{copy_uris}
</div>
)
break
}
2016-10-27 10:02:12 +13:00
}
render(){
if (!this.props.menu) return null;
2016-10-27 10:02:12 +13:00
var style = {
left: this.props.menu.position_x,
top: this.props.menu.position_y,
2016-10-27 10:02:12 +13:00
}
2017-04-21 09:10:47 +12:00
var height = 200 // TODO: use jquery to detect height
2017-03-01 08:28:10 +13:00
var className = "context-menu "+this.props.menu.context
2017-04-21 09:10:47 +12:00
if (this.state.submenu_expanded){
className += ' submenu-expanded'
}
if (this.props.menu.position_x > (window.innerWidth - 174)){
style.left = 'auto'
style.right = 10
}
if (this.props.menu.position_y > (window.innerHeight - height)){
2017-04-21 09:10:47 +12:00
style.top = 'auto'
style.bottom = 10
}
2016-10-27 10:02:12 +13:00
return (
2017-03-06 09:03:20 +13:00
<div id="context-menu" className={className} style={style}>
2017-02-27 08:44:02 +13:00
<div className="liner">
{this.renderTitle()}
2017-03-06 09:03:20 +13:00
{this.props.menu.context == 'custom' ? this.props.menu.options : this.renderItems()}
2017-02-27 08:44:02 +13:00
</div>
<div className="background" onClick={e => this.props.uiActions.hideContextMenu()}></div>
2016-10-27 10:02:12 +13:00
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
menu: state.ui.context_menu,
load_queue: state.ui.load_queue,
2017-08-22 08:38:03 +12:00
processes: state.ui.processes,
current_track: state.core.current_track,
current_tracklist: state.core.current_tracklist,
2017-08-13 21:04:59 +12:00
spotify_library_playlists: state.spotify.library_playlists,
spotify_library_playlists_loaded_all: state.spotify.library_playlists_loaded_all,
2017-08-13 21:04:59 +12:00
mopidy_library_playlists: state.mopidy.library_playlists,
mopidy_library_playlists_loaded_all: state.mopidy.library_playlists_loaded_all,
2017-08-13 21:04:59 +12:00
spotify_library_artists: state.spotify.library_artists,
mopidy_library_artists: state.mopidy.library_artists,
spotify_library_albums: state.spotify.library_albums,
mopidy_library_albums: state.mopidy.library_albums,
playlists: state.core.playlists,
tracks: state.core.tracks,
spotify_authorized: state.spotify.authorization,
lastfm_authorized: state.lastfm.session
}
2016-10-27 10:02:12 +13:00
}
const mapDispatchToProps = (dispatch) => {
return {
2017-08-02 21:11:22 +12:00
coreActions: bindActionCreators(coreActions, dispatch),
2016-10-27 10:02:12 +13:00
uiActions: bindActionCreators(uiActions, dispatch),
pusherActions: bindActionCreators(pusherActions, dispatch),
2016-10-27 10:02:12 +13:00
spotifyActions: bindActionCreators(spotifyActions, dispatch),
lastfmActions: bindActionCreators(lastfmActions, dispatch),
2016-10-27 10:02:12 +13:00
mopidyActions: bindActionCreators(mopidyActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ContextMenu)