diff --git a/src/js/components/ContextMenu.js b/src/js/components/ContextMenu.js index 207b019f..537afee6 100755 --- a/src/js/components/ContextMenu.js +++ b/src/js/components/ContextMenu.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react' -import { Link } from 'react-router' +import { Link, hashHistory } from 'react-router' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import FontAwesome from 'react-fontawesome' @@ -30,12 +30,17 @@ class ContextMenu extends React.Component{ window.removeEventListener("click", this.handleClick, false) } - handleScroll(){ - if (this.props.menu) this.props.uiActions.hideContextMenu() + handleScroll(e){ + if (this.props.menu){ + this.props.uiActions.hideContextMenu() + } } - handleClick(){ - if (this.props.menu) this.props.uiActions.hideContextMenu() + handleClick(e){ + var target = e.target + if (this.props.menu && !target.classList.contains('context-menu-trigger')){ + this.props.uiActions.hideContextMenu() + } } playQueueItem(){ @@ -89,6 +94,10 @@ class ContextMenu extends React.Component{ this.props.uiActions.hideContextMenu(); } + goToUser(){ + hashHistory.push( global.baseURL +'user/'+ this.props.menu.item.owner.uri ); + } + copyURIs(e){ var temp = $(""); $("body").append(temp); @@ -100,6 +109,17 @@ class ContextMenu extends React.Component{ this.props.uiActions.hideContextMenu() } + copyLinks(e){ + var temp = $(""); + $("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(); } @@ -137,8 +157,10 @@ class ContextMenu extends React.Component{ { handleClick: 'playURIs', label: 'Play' }, { handleClick: 'playURIsNext', label: 'Play next' }, { handleClick: 'addToQueue', label: 'Add to queue' }, + { handleClick: 'goToArtist', label: 'Go to artist' }, // { handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO - { handleClick: 'copyURIs', label: 'Copy URI' } + { handleClick: 'copyURIs', label: 'Copy URI' }, + { handleClick: 'copyLinks', label: 'Copy link' } ] break @@ -146,15 +168,18 @@ class ContextMenu extends React.Component{ var items = [ //{ handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO { handleClick: 'startRadio', label: 'Start radio' }, - { handleClick: 'copyURIs', label: 'Copy URI' } + { handleClick: 'copyURIs', label: 'Copy URI' }, + { handleClick: 'copyLinks', label: 'Copy link' } ] break case 'playlist': var items = [ { handleClick: 'playURIs', label: 'Play' }, + { handleClick: 'goToUser', label: 'Go to user' }, // { handleClick: 'toggleFollow', label: 'Follow/unfollow' }, TODO - { handleClick: 'copyURIs', label: 'Copy URI' } + { handleClick: 'copyURIs', label: 'Copy URI' }, + { handleClick: 'copyLinks', label: 'Copy link' } ] break @@ -205,6 +230,11 @@ class ContextMenu extends React.Component{ return ( {style ?
: null} +
+ {helpers.uriSource(item.uri)} +   + {this.props.menu.context} +
{item.name}
) @@ -264,8 +294,10 @@ class ContextMenu extends React.Component{ return (
- {this.props.menu.item ? this.renderTitle() : null} - {this.renderItems()} +
+ {this.props.menu.item ? this.renderTitle() : null} + {this.renderItems()} +
); } diff --git a/src/js/views/Album.js b/src/js/views/Album.js index 640d0eee..ebfe8d3a 100755 --- a/src/js/views/Album.js +++ b/src/js/views/Album.js @@ -49,6 +49,16 @@ class Album extends React.Component{ } } + handleContextMenu(e){ + var data = { + e: e, + context: 'album', + item: this.props.album, + uris: [this.props.params.uri] + } + this.props.uiActions.showContextMenu(data) + } + loadAlbum( props = this.props ){ switch( helpers.uriSource( props.params.uri ) ){ @@ -119,6 +129,7 @@ class Album extends React.Component{
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? : null } +
diff --git a/src/js/views/App.js b/src/js/views/App.js index 44f9b279..0c49d208 100755 --- a/src/js/views/App.js +++ b/src/js/views/App.js @@ -122,7 +122,11 @@ class App extends React.Component{ if (this.props.dragger && this.props.dragger.active) className += ' dragging' if (this.props.sidebar_open) className += ' sidebar-open' if (this.props.modal) className += ' modal-open' - if (helpers.isTouchDevice() || this.props.emulate_touch) className += ' can-touch' + if (helpers.isTouchDevice() || this.props.emulate_touch){ + className += ' touch' + } else { + className += ' notouch' + } return (
diff --git a/src/js/views/Artist.js b/src/js/views/Artist.js index aea04edc..0a4b32ac 100755 --- a/src/js/views/Artist.js +++ b/src/js/views/Artist.js @@ -54,6 +54,16 @@ class Artist extends React.Component{ } } + handleContextMenu(e){ + var data = { + e: e, + context: 'artist', + item: this.props.artist, + uris: [this.props.params.uri] + } + this.props.uiActions.showContextMenu(data) + } + loadArtist( props = this.props ){ switch( helpers.uriSource( props.params.uri ) ){ @@ -204,7 +214,7 @@ class Artist extends React.Component{
{ can_play_radio ? : null} { can_follow ? : null} - +
{ this.renderSubViewMenu() }
diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index fef4e085..a7191e3d 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -39,6 +39,16 @@ class Playlist extends React.Component{ } } + handleContextMenu(e){ + var data = { + e: e, + context: (this.props.playlist.can_edit ? 'editable-playlist' : 'playlist'), + item: this.props.playlist, + uris: [this.props.params.uri] + } + this.props.uiActions.showContextMenu(data) + } + loadPlaylist( props = this.props ){ switch( helpers.uriSource( props.params.uri ) ){ @@ -97,7 +107,7 @@ class Playlist extends React.Component{
- this.delete() } /> +
) @@ -107,7 +117,7 @@ class Playlist extends React.Component{
- this.unfollow() } /> +
) } @@ -115,6 +125,7 @@ class Playlist extends React.Component{
+
) @@ -122,6 +133,7 @@ class Playlist extends React.Component{ return (
+
) } diff --git a/src/scss/components/_context-menu.scss b/src/scss/components/_context-menu.scss index 1b634625..e327c6a2 100755 --- a/src/scss/components/_context-menu.scss +++ b/src/scss/components/_context-menu.scss @@ -4,169 +4,154 @@ left: 0; top: 0; z-index: 99; - background: $dark_grey; - color: #FFFFFF; - &.right-align { - margin-left: -140px; - } + .liner { + background: $dark_grey; + color: #FFFFFF; - &.right-align-submenu .submenu { - left: auto !important; - right: 140px !important; - } - - &.bottom-align-submenu .submenu { - top: auto !important; - bottom: 0 !important; - } - - .title { - cursor: pointer; - display: block; - padding: 8px 12px; - width: 140px; - font-weight: bold; - box-sizing: border-box; - position: relative; - overflow: hidden; - text-decoration: none; - background: $darkest_grey; - - .background { - @include blur(5px); - background-size: cover; - background-position: 50% 20%; - opacity: 0.5; - position: absolute; - top: -10px; - left: -10px; - bottom: -10px; - right: -10px; - z-index: 1; + &.right-align { + margin-left: -140px; } - .text { - @include one_line_text(); - position: relative; - z-index: 2; - color: #FFFFFF; + &.right-align-submenu .submenu { + left: auto !important; + right: 140px !important; } - &:hover{ - .background { - opacity: 0.7; - } + &.bottom-align-submenu .submenu { + top: auto !important; + bottom: 0 !important; } - } - .menu-item-wrapper { - display: block; - position: relative; - - .menu-item { + .title { cursor: pointer; display: block; padding: 8px 12px; width: 140px; - box-sizing: border-box; - } + font-weight: bold; + box-sizing: border-box; + position: relative; + overflow: hidden; + text-decoration: none; + background: $darkest_grey; - .icon { - display: none; - } + .background { + @include blur(5px); + background-size: cover; + background-position: 50% 20%; + opacity: 0.5; + position: absolute; + top: -10px; + left: -10px; + bottom: -10px; + right: -10px; + z-index: 1; + } - .submenu-icon { - font-size: 10px; - float: right; - padding-top: 4px; - } + .text { + @include one_line_text(); + position: relative; + z-index: 2; + color: #FFFFFF; + } - .submenu { - display: none; - position: absolute; - left: 140px; - top: 0; - max-height: 200px; - overflow-y: scroll; - background: lighten($dark_grey, 5%); + .type { + position: relative; + z-index: 2; + color: #FFFFFF; + opacity: 0.5; + font-weight: 200; + text-transform: capitalize; + } - .menu-item { - width: 140px; - &:hover { - background: lighten($dark_grey, 10%); + &:hover{ + .background { + opacity: 0.7; } } } - .menu-item { - border-top: 1px solid lighten($dark_grey, 8%); - } + .menu-item-wrapper { + display: block; + position: relative; - &:hover { .menu-item { - background: lighten($dark_grey, 5%); - } - .submenu { + cursor: pointer; display: block; + padding: 8px 12px; + width: 140px; + box-sizing: border-box; + } + + .icon { + display: none; + } + + .submenu-icon { + font-size: 10px; + float: right; + padding-top: 4px; + } + + .submenu { + display: none; + position: absolute; + left: 140px; + top: 0; + max-height: 200px; + overflow-y: scroll; + background: lighten($dark_grey, 5%); + + .menu-item { + width: 140px; + &:hover { + background: lighten($dark_grey, 10%); + } + } + } + + .menu-item { + border-top: 1px solid lighten($dark_grey, 8%); + } + + &:hover { + .menu-item { + background: lighten($dark_grey, 5%); + } + .submenu { + display: block; + } + } + } + } + + @include responsive( $bp_medium ){ + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + margin: 0 !important; + background: rgba(10, 10, 10, 0.95); + overflow-y: scroll; + + .liner { + width: 250px; + margin: 30px auto; + max-width: 90vw; + + .title { + padding: 16px 20px; + width: 100%; + box-sizing: border-box; + } + + .menu-item-wrapper { + .menu-item { + padding: 16px 20px; + width: 100%; + box-sizing: border-box; + } } } } } - -.touch-context-menu { - position: fixed; - z-index: 99; - bottom: 0; - left: 0; - right: 0; - top: auto; - background: $blue; - color: #FFFFFF; - - .menu-item-wrapper { - display: inline-block; - - .menu-item { - display: inline-block; - text-align: center; - width: 50px; - height: 44px; - padding-top: 6px; - border: 0; - vertical-align: top; - - &:hover { - background: inherit; - } - - &:active, - &:focus { - background: rgba(255,255,255,0.2); - } - - .icon { - padding: 5px; - display: inline-block; - } - - .label { - display: block; - font-size: 10px; - } - - .submenu-icon { - display: none !important; - } - } - - &.cancel { - float: right; - opacity: 0.5; - } - - &:not(:first-child) .menu-item { - border-left: 1px solid rgba(255,255,255,0.2) !important; - } - } -} \ No newline at end of file diff --git a/src/scss/global/_forms.scss b/src/scss/global/_forms.scss index 1f4c80e9..729bf5a2 100755 --- a/src/scss/global/_forms.scss +++ b/src/scss/global/_forms.scss @@ -144,6 +144,39 @@ input[type="submit"] { } } + &.context-menu-trigger { + border-color: transparent; + padding: 6px; + font-size: 20px; + min-width: 0; + line-height: 20px; + color: #000000; + + &:hover { + border-color: transparent; + background: rgba(0,0,0,0.1); + } + + &:active { + color: #FFFFFF; + background: #000000; + } + + &.white { + color: #FFFFFF; + + &:hover { + border-color: transparent; + background: rgba(255,255,255,0.1); + } + + &:active { + color: #000000; + background: #FFFFFF; + } + } + } + &[disabled], &[disabled="disabled"]{ opacity: 0.5;