Context menu trigger; Unified context menu
This commit is contained in:
@ -28,7 +28,7 @@ class AlbumGrid extends React.Component{
|
||||
e: e,
|
||||
context: 'album',
|
||||
uris: [item.uri],
|
||||
item: item
|
||||
items: [item]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ class ArtistGrid extends React.Component{
|
||||
e: e,
|
||||
context: 'artist',
|
||||
uris: [item.uri],
|
||||
item: item
|
||||
items: [item]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
}
|
||||
|
||||
@ -30,6 +30,14 @@ class ContextMenu extends React.Component{
|
||||
window.removeEventListener("click", this.handleClick, false)
|
||||
}
|
||||
|
||||
componentWillReceiveProps( nextProps ){
|
||||
if (nextProps.menu){
|
||||
$('body').addClass('context-menu-open')
|
||||
} else {
|
||||
$('body').removeClass('context-menu-open')
|
||||
}
|
||||
}
|
||||
|
||||
handleScroll(e){
|
||||
if (this.props.menu){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
@ -37,6 +45,10 @@ class ContextMenu extends React.Component{
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
if (helpers.isTouchDevice()){
|
||||
return null
|
||||
}
|
||||
|
||||
var target = e.target
|
||||
if (this.props.menu && !target.classList.contains('context-menu-trigger')){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
@ -44,58 +56,72 @@ class ContextMenu extends React.Component{
|
||||
}
|
||||
|
||||
playQueueItem(){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
var tracks = this.props.menu.items;
|
||||
this.props.mopidyActions.changeTrack( tracks[0].tlid );
|
||||
this.props.uiActions.hideContextMenu();
|
||||
this.props.mopidyActions.changeTrack( tracks[0].tlid )
|
||||
}
|
||||
|
||||
removeFromQueue(){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
var tracks = this.props.menu.items;
|
||||
var tracks_tlids = [];
|
||||
for( var i = 0; i < tracks.length; i++ ){
|
||||
tracks_tlids.push( tracks[i].tlid );
|
||||
}
|
||||
this.props.mopidyActions.removeTracks( tracks_tlids );
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
|
||||
playURIs(){
|
||||
this.props.mopidyActions.playURIs(this.props.menu.uris, this.props.menu.tracklist_uri);
|
||||
this.props.uiActions.hideContextMenu();
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.mopidyActions.playURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
}
|
||||
|
||||
playURIsNext(){
|
||||
this.props.mopidyActions.enqueueURIsNext(this.props.menu.uris, this.props.menu.tracklist_uri);
|
||||
this.props.uiActions.hideContextMenu();
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.mopidyActions.enqueueURIsNext(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
}
|
||||
|
||||
addToPlaylist(){
|
||||
this.props.uiActions.openModal('add_to_playlist', { tracks_uris: this.props.menu.uris })
|
||||
this.props.uiActions.hideContextMenu();
|
||||
this.props.uiActions.openModal('add_to_playlist', { tracks_uris: this.props.menu.uris })
|
||||
}
|
||||
|
||||
addToQueue(){
|
||||
this.props.mopidyActions.enqueueURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.mopidyActions.enqueueURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
}
|
||||
|
||||
addTracksToPlaylist(playlist_uri){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.uiActions.addTracksToPlaylist(playlist_uri, this.props.menu.uris)
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
|
||||
removeFromPlaylist(){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.uiActions.removeTracksFromPlaylist(this.props.menu.tracklist_uri, this.props.menu.indexes)
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
|
||||
startRadio(){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
this.props.pusherActions.startRadio(this.props.menu.uris)
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
|
||||
goToArtist(){
|
||||
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){
|
||||
return null
|
||||
} else {
|
||||
this.props.uiActions.hideContextMenu()
|
||||
hashHistory.push( global.baseURL +'artist/'+ this.props.menu.items[0].artists[0].uri )
|
||||
}
|
||||
}
|
||||
|
||||
goToUser(){
|
||||
hashHistory.push( global.baseURL +'user/'+ this.props.menu.item.owner.uri );
|
||||
if (!this.props.menu.items || this.props.menu.items.length <= 0){
|
||||
return null
|
||||
} else {
|
||||
this.props.uiActions.hideContextMenu()
|
||||
hashHistory.push( global.baseURL +'user/'+ this.props.menu.items[0].owner.uri )
|
||||
}
|
||||
}
|
||||
|
||||
copyURIs(e){
|
||||
@ -109,17 +135,6 @@ class ContextMenu extends React.Component{
|
||||
this.props.uiActions.hideContextMenu()
|
||||
}
|
||||
|
||||
copyLinks(e){
|
||||
var temp = $("<input>");
|
||||
$("body").append(temp);
|
||||
temp.val(this.props.menu.item.external_urls.spotify).select();
|
||||
document.execCommand("copy");
|
||||
temp.remove();
|
||||
|
||||
this.props.uiActions.createNotification( "Copied link" )
|
||||
this.props.uiActions.hideContextMenu()
|
||||
}
|
||||
|
||||
closeAndDeselectTracks(){
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
@ -159,8 +174,7 @@ class ContextMenu extends React.Component{
|
||||
{ handleClick: 'addToQueue', label: 'Add to queue' },
|
||||
{ handleClick: 'goToArtist', label: 'Go to artist' },
|
||||
// { handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' },
|
||||
{ handleClick: 'copyLinks', label: 'Copy link' }
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' }
|
||||
]
|
||||
break
|
||||
|
||||
@ -168,8 +182,7 @@ class ContextMenu extends React.Component{
|
||||
var items = [
|
||||
//{ handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO
|
||||
{ handleClick: 'startRadio', label: 'Start radio' },
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' },
|
||||
{ handleClick: 'copyLinks', label: 'Copy link' }
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' }
|
||||
]
|
||||
break
|
||||
|
||||
@ -178,8 +191,7 @@ class ContextMenu extends React.Component{
|
||||
{ handleClick: 'playURIs', label: 'Play' },
|
||||
{ handleClick: 'goToUser', label: 'Go to user' },
|
||||
// { handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' },
|
||||
{ handleClick: 'copyLinks', label: 'Copy link' }
|
||||
{ handleClick: 'copyURIs', label: 'Copy URI' }
|
||||
]
|
||||
break
|
||||
|
||||
@ -220,24 +232,52 @@ class ContextMenu extends React.Component{
|
||||
}
|
||||
|
||||
renderTitle(){
|
||||
var item = this.props.menu.item
|
||||
var style = null
|
||||
if (item && item.images){
|
||||
style = {
|
||||
backgroundImage: 'url('+helpers.sizedImages(item.images).medium+')'
|
||||
}
|
||||
if (!this.props.menu.items || this.props.menu.items.length <= 0){
|
||||
return null
|
||||
}
|
||||
|
||||
switch (this.props.menu.context){
|
||||
|
||||
case 'artist':
|
||||
case 'album':
|
||||
case 'playlist':
|
||||
var item = this.props.menu.items[0]
|
||||
var style = null
|
||||
if (item && item.images){
|
||||
style = {
|
||||
backgroundImage: 'url('+helpers.sizedImages(item.images).medium+')'
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Link className="title" to={global.baseURL+helpers.uriType(item.uri)+'/'+item.uri}>
|
||||
{style ? <div className="background" style={style}></div> : null}
|
||||
<div className="type">
|
||||
{helpers.uriSource(item.uri)}
|
||||
|
||||
{this.props.menu.context}
|
||||
</div>
|
||||
<div className="text">{item.name}</div>
|
||||
</Link>
|
||||
)
|
||||
break
|
||||
|
||||
default:
|
||||
return (
|
||||
<span className="title">
|
||||
<div className="type">
|
||||
{helpers.uriSource(this.props.menu.items[0].uri)}
|
||||
|
||||
{this.props.menu.context}s
|
||||
</div>
|
||||
<div className="text">
|
||||
{this.props.menu.items.length} items
|
||||
</div>
|
||||
</span>
|
||||
)
|
||||
break
|
||||
|
||||
}
|
||||
return (
|
||||
<Link className="title" to={global.baseURL+helpers.uriType(item.uri)+'/'+item.uri}>
|
||||
{style ? <div className="background" style={style}></div> : null}
|
||||
<div className="type">
|
||||
{helpers.uriSource(item.uri)}
|
||||
|
||||
{this.props.menu.context}
|
||||
</div>
|
||||
<div className="text">{item.name}</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
renderItems(){
|
||||
@ -295,9 +335,10 @@ class ContextMenu extends React.Component{
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
<div className="liner">
|
||||
{this.props.menu.item ? this.renderTitle() : null}
|
||||
{this.renderTitle()}
|
||||
{this.renderItems()}
|
||||
</div>
|
||||
<div className="background" onClick={e => this.props.uiActions.hideContextMenu()}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
24
src/js/components/ContextMenuTrigger.js
Executable file
24
src/js/components/ContextMenuTrigger.js
Executable file
@ -0,0 +1,24 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import FontAwesome from 'react-fontawesome'
|
||||
|
||||
export default class ContextMenuTrigger extends React.Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(){
|
||||
var className = 'context-menu-trigger'
|
||||
if (this.props.className){
|
||||
className += ' '+this.props.className
|
||||
}
|
||||
return (
|
||||
<button
|
||||
className={className}
|
||||
onClick={e => this.props.onTrigger(e)}>
|
||||
<FontAwesome name="ellipsis-v" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,14 @@ class Modal extends React.Component{
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentWillReceiveProps( nextProps ){
|
||||
if (nextProps.modal){
|
||||
$('body').addClass('modal-open')
|
||||
} else {
|
||||
$('body').removeClass('modal-open')
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.props.modal ) return null;
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ class PlaylistGrid extends React.Component{
|
||||
e: e,
|
||||
context: 'playlist',
|
||||
uris: [item.uri],
|
||||
item: item
|
||||
items: [item]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { Link, hashHistory } from 'react-router'
|
||||
import { createStore, bindActionCreators } from 'redux'
|
||||
import FontAwesome from 'react-fontawesome'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
|
||||
@ -19,8 +20,28 @@ class SearchForm extends React.Component{
|
||||
}
|
||||
|
||||
handleSubmit(e){
|
||||
e.preventDefault();
|
||||
hashHistory.push(global.baseURL+'search/'+this.state.query);
|
||||
e.preventDefault()
|
||||
|
||||
// check for uri type matching
|
||||
switch (helpers.uriType(this.state.query)){
|
||||
|
||||
case 'album':
|
||||
hashHistory.push(global.baseURL+'album/'+this.state.query)
|
||||
break
|
||||
|
||||
case 'artist':
|
||||
hashHistory.push(global.baseURL+'artist/'+this.state.query)
|
||||
break
|
||||
|
||||
case 'playlist':
|
||||
hashHistory.push(global.baseURL+'playlist/'+this.state.query)
|
||||
break
|
||||
|
||||
default:
|
||||
hashHistory.push(global.baseURL+'search/'+this.state.query)
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@ -1,164 +0,0 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Link } from 'react-router'
|
||||
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 pusherActions from '../services/pusher/actions'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
|
||||
class TouchContextMenu extends React.Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
close(){
|
||||
this.props.uiActions.hideTouchContextMenu();
|
||||
}
|
||||
|
||||
playQueueItem(){
|
||||
var tracks = this.props.menu.items
|
||||
this.props.mopidyActions.changeTrack( tracks[0].tlid )
|
||||
this.close()
|
||||
}
|
||||
|
||||
removeFromQueue(e){
|
||||
var tracks = this.props.menu.items
|
||||
var tracks_tlids = []
|
||||
for( var i = 0; i < tracks.length; i++ ){
|
||||
tracks_tlids.push( tracks[i].tlid );
|
||||
}
|
||||
this.props.mopidyActions.removeTracks( tracks_tlids )
|
||||
this.close()
|
||||
}
|
||||
|
||||
playURIs(e){
|
||||
this.props.mopidyActions.playURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
this.close()
|
||||
}
|
||||
|
||||
playURIsNext(e){
|
||||
this.props.mopidyActions.enqueueURIsNext(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
this.close()
|
||||
}
|
||||
|
||||
addToPlaylist(e){
|
||||
this.props.uiActions.openModal('add_to_playlist', { tracks_uris: this.props.menu.uris })
|
||||
this.close()
|
||||
}
|
||||
|
||||
addToQueue(e){
|
||||
this.props.mopidyActions.enqueueURIs(this.props.menu.uris, this.props.menu.tracklist_uri)
|
||||
this.close()
|
||||
}
|
||||
|
||||
removeFromPlaylist(e){
|
||||
this.props.uiActions.removeTracksFromPlaylist(this.props.menu.tracklist_uri, this.props.menu.indexes)
|
||||
this.close()
|
||||
}
|
||||
|
||||
startRadio(e){
|
||||
this.props.pusherActions.startRadio(this.props.menu.uris)
|
||||
this.close()
|
||||
}
|
||||
|
||||
getItems(){
|
||||
switch (this.props.menu.context) {
|
||||
|
||||
case 'queue-track':
|
||||
var items = [
|
||||
{ handleClick: 'playQueueItem', label: 'Play', icon: 'play' },
|
||||
{ handleClick: 'addToPlaylist', label: 'Playlist', icon: 'plus' },
|
||||
{ handleClick: 'removeFromQueue', label: 'Remove', icon: 'trash' }
|
||||
]
|
||||
break
|
||||
|
||||
case 'editable-playlist-track':
|
||||
var items = [
|
||||
{ handleClick: 'playURIs', label: 'Play', icon: 'play' },
|
||||
{ handleClick: 'playURIsNext', label: 'Next', icon: 'play' },
|
||||
{ handleClick: 'addToQueue', label: 'Queue', icon: 'plus' },
|
||||
{ handleClick: 'addToPlaylist', label: 'Playlist', icon: 'plus' },
|
||||
{ handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' },
|
||||
{ handleClick: 'removeFromPlaylist', label: 'Remove', icon: 'trash' }
|
||||
]
|
||||
break
|
||||
|
||||
default:
|
||||
var items = [
|
||||
{ handleClick: 'playURIs', label: 'Play', icon: 'play' },
|
||||
{ handleClick: 'playURIsNext', label: 'Next', icon: 'play' },
|
||||
{ handleClick: 'addToQueue', label: 'Queue', icon: 'plus' },
|
||||
{ handleClick: 'addToPlaylist', label: 'Playlist', icon: 'plus' },
|
||||
{ handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' }
|
||||
]
|
||||
break
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
renderItems(){
|
||||
var items = this.getItems()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<span className="menu-item-wrapper" key={item.handleClick}>
|
||||
<a className="menu-item" onClick={e => this[item.handleClick]()}>
|
||||
<FontAwesome className="icon" fixedWidth name={item.icon} />
|
||||
<span className="label">{ item.label }</span>
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
})
|
||||
}
|
||||
<span className="menu-item-wrapper cancel" key="cancel">
|
||||
<a className="menu-item" onClick={e => this.close()}>
|
||||
<FontAwesome className="icon" fixedWidth name="close" />
|
||||
<span className="label">Cancel</span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.props.menu ) return null;
|
||||
|
||||
return (
|
||||
<div className="touch-context-menu">
|
||||
{this.renderItems()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
menu: state.ui.touch_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),
|
||||
pusherActions: bindActionCreators(pusherActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TouchContextMenu)
|
||||
@ -1,10 +1,10 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Link } from 'react-router'
|
||||
|
||||
import FontAwesome from 'react-fontawesome'
|
||||
import ArtistSentence from './ArtistSentence'
|
||||
import Dater from './Dater'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
|
||||
export default class Track extends React.Component{
|
||||
@ -140,7 +140,6 @@ export default class Track extends React.Component{
|
||||
{ this.props.track.selected ? <FontAwesome name="check" className="select-state" fixedWidth /> : null }
|
||||
{ this.props.track.playing ? <FontAwesome name="play" className="play-state" fixedWidth /> : null }
|
||||
{ track_columns }
|
||||
{ this.props.show_source_icon ? <FontAwesome className="source" name={helpers.sourceIcon(track.uri)} /> : null }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import FollowButton from '../components/FollowButton'
|
||||
import Dater from '../components/Dater'
|
||||
import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import SidebarToggleButton from '../components/SidebarToggleButton'
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
@ -53,7 +54,7 @@ class Album extends React.Component{
|
||||
var data = {
|
||||
e: e,
|
||||
context: 'album',
|
||||
item: this.props.album,
|
||||
items: [this.props.album],
|
||||
uris: [this.props.params.uri]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
@ -66,7 +67,6 @@ class Album extends React.Component{
|
||||
if (props.album && props.album.tracks && props.album.artists_uris){
|
||||
console.info('Loading album from index')
|
||||
}else{
|
||||
console.log(props.params.uri)
|
||||
this.props.spotifyActions.getAlbum( props.params.uri );
|
||||
}
|
||||
break;
|
||||
@ -129,7 +129,7 @@ class Album extends React.Component{
|
||||
<div className="actions">
|
||||
<button className="primary" onClick={e => this.play()}>Play</button>
|
||||
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton className="secondary" uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
|
||||
<button className="context-menu-trigger" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
|
||||
@ -9,7 +9,6 @@ import Sidebar from '../components/Sidebar'
|
||||
import MiniPlayer from '../components/MiniPlayer'
|
||||
import SidebarToggleButton from '../components/SidebarToggleButton'
|
||||
import ContextMenu from '../components/ContextMenu'
|
||||
import TouchContextMenu from '../components/TouchContextMenu'
|
||||
import Dragger from '../components/Dragger'
|
||||
import Modal from '../components/Modal/Modal'
|
||||
import Notifications from '../components/Notifications'
|
||||
@ -136,7 +135,6 @@ class App extends React.Component{
|
||||
{this.props.children}
|
||||
</main>
|
||||
<ContextMenu />
|
||||
<TouchContextMenu />
|
||||
<Dragger />
|
||||
<Modal />
|
||||
<Notifications />
|
||||
|
||||
@ -14,6 +14,7 @@ import ArtistList from '../components/ArtistList'
|
||||
import ArtistGrid from '../components/ArtistGrid'
|
||||
import FollowButton from '../components/FollowButton'
|
||||
import SidebarToggleButton from '../components/SidebarToggleButton'
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
@ -58,7 +59,7 @@ class Artist extends React.Component{
|
||||
var data = {
|
||||
e: e,
|
||||
context: 'artist',
|
||||
item: this.props.artist,
|
||||
items: [this.props.artist],
|
||||
uris: [this.props.params.uri]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
@ -214,7 +215,7 @@ class Artist extends React.Component{
|
||||
<div className="actions">
|
||||
{ can_play_radio ? <button className="primary" onClick={e => this.props.pusherActions.startRadio([this.props.artist.uri])}>Start radio</button> : null}
|
||||
{ can_follow ? <FollowButton className="white" uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null}
|
||||
<button className="context-menu-trigger white" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger className="white" onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
{ this.renderSubViewMenu() }
|
||||
</div>
|
||||
|
||||
@ -13,6 +13,7 @@ import ConfirmationButton from '../components/ConfirmationButton'
|
||||
import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import FollowButton from '../components/FollowButton'
|
||||
import SidebarToggleButton from '../components/SidebarToggleButton'
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
@ -43,7 +44,7 @@ class Playlist extends React.Component{
|
||||
var data = {
|
||||
e: e,
|
||||
context: (this.props.playlist.can_edit ? 'editable-playlist' : 'playlist'),
|
||||
item: this.props.playlist,
|
||||
items: [this.props.playlist],
|
||||
uris: [this.props.params.uri]
|
||||
}
|
||||
this.props.uiActions.showContextMenu(data)
|
||||
@ -107,7 +108,7 @@ class Playlist extends React.Component{
|
||||
<div className="actions">
|
||||
<button className="primary" onClick={ e => this.play() }>Play</button>
|
||||
<button className="secondary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name }) }>Edit</button>
|
||||
<button className="context-menu-trigger" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -117,7 +118,7 @@ class Playlist extends React.Component{
|
||||
<div className="actions">
|
||||
<button className="primary" onClick={ e => this.play() }>Play</button>
|
||||
<button className="secondary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
|
||||
<button className="context-menu-trigger" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -125,7 +126,7 @@ class Playlist extends React.Component{
|
||||
<div className="actions">
|
||||
<button className="primary" onClick={ e => this.play() }>Play</button>
|
||||
<FollowButton className="secondary" uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
|
||||
<button className="context-menu-trigger" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -133,7 +134,7 @@ class Playlist extends React.Component{
|
||||
return (
|
||||
<div className="actions">
|
||||
<button className="primary" onClick={ e => this.play() }>Play</button>
|
||||
<button className="context-menu-trigger" onClick={e => this.handleContextMenu(e)}><FontAwesome name="ellipsis-v" /></button>
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import PlaylistGrid from '../components/PlaylistGrid'
|
||||
import FollowButton from '../components/FollowButton'
|
||||
import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import Header from '../components/Header'
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
@ -71,6 +72,7 @@ class User extends React.Component{
|
||||
|
||||
<div className="actions">
|
||||
<FollowButton className="secondary" uri={this.props.params.uri} addText="Follow" removeText="Unfollow" />
|
||||
<ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="main">
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
}
|
||||
|
||||
.title {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 8px 12px;
|
||||
width: 140px;
|
||||
@ -131,13 +130,24 @@
|
||||
bottom: 0 !important;
|
||||
left: 0 !important;
|
||||
margin: 0 !important;
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
overflow-y: scroll;
|
||||
|
||||
.background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.liner {
|
||||
width: 250px;
|
||||
margin: 30px auto;
|
||||
max-width: 90vw;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.title {
|
||||
padding: 16px 20px;
|
||||
|
||||
@ -18,13 +18,6 @@
|
||||
margin-bottom: -1px;
|
||||
@include clearfix;
|
||||
|
||||
.source {
|
||||
color: $mid_grey;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: $yellow !important;
|
||||
}
|
||||
@ -91,10 +84,28 @@
|
||||
padding: 7px 10px 7px 20px;
|
||||
|
||||
.col {
|
||||
&.name { width: 50%; }
|
||||
&.artists { width: 50%; }
|
||||
&.album { width: 50%; padding-left: 50%; color: $mid_grey; }
|
||||
&.duration { display: none; }
|
||||
&.name {
|
||||
width: 90%;
|
||||
padding-right: 10%;
|
||||
}
|
||||
|
||||
&.duration {
|
||||
width: auto;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&.artists,
|
||||
&.album {
|
||||
width: auto;
|
||||
color: $mid_grey;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.album {
|
||||
@include bullet();
|
||||
}
|
||||
}
|
||||
|
||||
&.header {
|
||||
@ -107,7 +118,6 @@
|
||||
left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -170,6 +180,26 @@
|
||||
&.album { width: 25%; }
|
||||
&.added { width: 20%; }
|
||||
}
|
||||
|
||||
@include responsive( $bp_medium ){
|
||||
.col {
|
||||
&.name {
|
||||
width: 90%;
|
||||
padding-right: 10%;
|
||||
}
|
||||
|
||||
&.artists,
|
||||
&.album {
|
||||
width: auto;
|
||||
color: $mid_grey;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.added {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,12 @@ body {
|
||||
&.modal-open {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@include responsive( $bp_medium ){
|
||||
&.context-menu-open {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main,
|
||||
@ -251,14 +257,7 @@ footer {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:first-child){
|
||||
padding-left: 14px;
|
||||
|
||||
&::before {
|
||||
display: inline-block;
|
||||
content: '•';
|
||||
margin-left: -8px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
@include bullet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,8 +38,7 @@ input[type="submit"] {
|
||||
padding: 6px 20px;
|
||||
min-width: 160px;
|
||||
border: 0;
|
||||
margin: 0 10px 20px 0;
|
||||
margin-right: 20px;
|
||||
margin: 0 20px 10px 0;
|
||||
text-align: center;
|
||||
border: 2px solid $mid_grey;
|
||||
color: $mid_grey;
|
||||
@ -147,10 +146,16 @@ input[type="submit"] {
|
||||
&.context-menu-trigger {
|
||||
border-color: transparent;
|
||||
padding: 6px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 20px;
|
||||
min-width: 0;
|
||||
line-height: 20px;
|
||||
color: #000000;
|
||||
vertical-align: bottom;
|
||||
|
||||
.fa {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: transparent;
|
||||
@ -192,7 +197,8 @@ input[type="submit"] {
|
||||
}
|
||||
|
||||
@include responsive( $bp_medium ){
|
||||
min-width: 140px;
|
||||
min-width: 120px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@include responsive( $bp_narrow ){
|
||||
|
||||
@ -32,6 +32,17 @@ $bp_shallow: 650px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bullet {
|
||||
padding-left: 14px;
|
||||
|
||||
&:before {
|
||||
display: inline-block;
|
||||
content: '\2022';
|
||||
margin-left: -8px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin animate( $duration: 0.2s, $easing: ease-in-out ){
|
||||
-webkit-transition: all $duration $easing;
|
||||
-moz-transition: all $duration $easing;
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
.actions {
|
||||
padding-bottom: 5px;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.sub-views {
|
||||
|
||||
Reference in New Issue
Block a user