import React, { PropTypes } from 'react' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import FontAwesome from 'react-fontawesome' import TrackList from './TrackList' import * as helpers from '../helpers' import * as uiActions from '../services/ui/actions' import * as mopidyActions from '../services/mopidy/actions' import * as spotifyActions from '../services/spotify/actions' class ContextMenu extends React.Component{ constructor(props) { super(props); this.handleScroll = this.handleScroll.bind(this) this.handleClick = this.handleClick.bind(this) } componentDidMount(){ window.addEventListener("scroll", this.handleScroll, false) window.addEventListener("click", this.handleClick, false) } componentWillUnmount(){ window.removeEventListener("scroll", this.handleScroll, false) window.removeEventListener("click", this.handleClick, false) } handleScroll(){ if( this.props.context_menu.show && this.props.context_menu.trigger == 'click' ){ this.props.uiActions.hideContextMenu(); } } handleClick(){ if( this.props.context_menu.show && this.props.context_menu.trigger == 'click' ){ this.props.uiActions.hideContextMenu(); } } playQueueItem(){ var selectedTracks = this.props.context_menu.data.selected_tracks; this.props.mopidyActions.changeTrack( selectedTracks[0].tlid ); this.props.uiActions.hideContextMenu(); } removeFromQueue(){ var selected_tracks = this.props.context_menu.data.selected_tracks; var selected_tracks_tlids = []; for( var i = 0; i < selected_tracks.length; i++ ){ selected_tracks_tlids.push( selected_tracks[i].tlid ); } this.props.mopidyActions.removeTracks( selected_tracks_tlids ); this.props.uiActions.hideContextMenu(); } playItems(){ var selected_tracks_uris = helpers.asURIs(this.props.context_menu.data.selected_tracks) this.props.mopidyActions.playURIs(selected_tracks_uris); this.props.uiActions.hideContextMenu(); } playItemsNext(){ var selected_tracks_uris = helpers.asURIs(this.props.context_menu.data.selected_tracks) this.props.mopidyActions.enqueueTracksNext(selected_tracks_uris); this.props.uiActions.hideContextMenu(); } addToPlaylist(){ var selected_tracks_uris = helpers.asURIs(this.props.context_menu.data.selected_tracks) this.props.uiActions.openModal( 'add_to_playlist', { tracks_uris: selected_tracks_uris } ) this.props.uiActions.hideContextMenu(); } addToQueue(){ var selected_tracks_uris = helpers.asURIs(this.props.context_menu.data.selected_tracks) this.props.mopidyActions.enqueueTracks(selected_tracks_uris); this.props.uiActions.hideContextMenu(); } addTracksToPlaylist( playlist_uri ){ var selected_tracks_uris = helpers.asURIs(this.props.context_menu.data.selected_tracks) this.props.uiActions.addTracksToPlaylist( playlist_uri, selected_tracks_uris ) this.props.uiActions.hideContextMenu(); } removeFromPlaylist(){ this.props.uiActions.removeTracksFromPlaylist( this.props.playlist.uri, this.props.context_menu.data.selected_tracks_indexes ) this.props.uiActions.hideContextMenu(); } copyURIs(){ var uris = ''; for( var i = 0; i < this.props.context_menu.data.selected_tracks.length; i++ ){ if( i > 0 ) uris += ',' uris += this.props.context_menu.data.selected_tracks[i].uri } console.log('Yet to be implemented', uris) this.props.uiActions.hideContextMenu() } closeAndDeselectTracks(){ this.props.uiActions.hideContextMenu(); } renderPlaylistSubmenu(){ var playlists = [] for (var uri in this.props.playlists){ if (this.props.playlists[uri].can_edit) playlists.push( this.props.playlists[uri]) } playlists = helpers.sortItems(playlists, 'name') return (
{ playlists.map( playlist => { return ( this.addTracksToPlaylist(playlist.uri) }> { playlist.name } ) }) }
) } getItems(trigger){ switch (this.props.context_menu.context) { case 'queue': var items = [ { handleClick: 'playQueueItem', label: 'Play', icon: 'play' }, { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true }, { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' }, { handleClick: 'removeFromQueue', label: 'Remove', icon: 'trash' } ] break case 'editable-playlist': var items = [ { handleClick: 'playItems', label: 'Play', icon: 'play' }, { handleClick: 'playItemsNext', 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 default: var items = [ { handleClick: 'playItems', label: 'Play', icon: 'play' }, { handleClick: 'playItemsNext', 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' } ] break } return items } renderItems(trigger){ var items = this.getItems(trigger) var closeItem = ( this.closeAndDeselectTracks(e) }> Cancel ) return (
{ items.map((item, index) => { if( item.playlists ){ return ( this[item.handleClick](e) }> { item.label } { this.renderPlaylistSubmenu() } ) }else{ return ( this[item.handleClick](e) }> { item.label } ) } }) } { trigger == 'touch' ? closeItem : null }
) } render(){ if( !this.props.context_menu.show ) return null; var style = { left: this.props.context_menu.position_x, top: this.props.context_menu.position_y, } var className = 'context-menu' if (this.props.emulate_touch) { className += ' touch' var trigger = 'touch' } else { className += ' '+this.props.context_menu.trigger var trigger = this.props.context_menu.trigger } var items = this.getItems(trigger) var height = 0 if (items) height = items.length * 34 // this is an approximation of how tall each menu item is if (this.props.context_menu.position_x > (window.innerWidth - 154)) className += ' right-align' if (this.props.context_menu.position_x > (window.innerWidth - 308)) className += ' right-align-submenu' if (this.props.context_menu.position_y > (window.innerHeight - height)){ style.top = style.top - height className += ' bottom-align-submenu' } return (
{ this.renderItems(trigger) }
); } } const mapStateToProps = (state, ownProps) => { return { emulate_touch: state.ui.emulate_touch, context_menu: state.ui.context_menu, current_track: state.ui.current_track, current_tracklist: state.ui.current_tracklist, playlist: state.ui.playlist, playlists: state.ui.playlists } } const mapDispatchToProps = (dispatch) => { return { uiActions: bindActionCreators(uiActions, dispatch), spotifyActions: bindActionCreators(spotifyActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch) } } export default connect(mapStateToProps, mapDispatchToProps)(ContextMenu)