Static cleanout; Sliders now true range sliders for drag support, fixes #297
This commit is contained in:
@ -1,34 +1,26 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import * as mopidyActions from '../../services/mopidy/actions'
|
||||
import * as helpers from '../../helpers';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
|
||||
class ProgressSlider extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.handleChange = helpers.throttle(this.handleChange.bind(this), 250);
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
var slider = e.target;
|
||||
if (slider.className != 'slider' ) slider = slider.parentElement;
|
||||
|
||||
var sliderX = e.clientX - slider.getBoundingClientRect().left;
|
||||
var sliderWidth = slider.getBoundingClientRect().width;
|
||||
var percent = (sliderX / sliderWidth ).toFixed(2);
|
||||
|
||||
if (this.props.connected && this.props.current_track){
|
||||
var destination_time = this.props.current_track.duration * percent;
|
||||
this.props.mopidyActions.setTimePosition(destination_time);
|
||||
this.setState({ animating: false });
|
||||
}
|
||||
}
|
||||
handleChange(value){
|
||||
this.props.mopidyActions.setTimePosition(this.props.current_track.duration * (value / 100));
|
||||
}
|
||||
|
||||
render(){
|
||||
var percent = 0;
|
||||
if (this.props.connected && this.props.current_track){
|
||||
if (this.props.connected && this.props.time_position && this.props.current_track){
|
||||
percent = this.props.time_position / this.props.current_track.duration;
|
||||
percent = percent * 100;
|
||||
if (percent > 1000){
|
||||
@ -37,8 +29,15 @@ class ProgressSlider extends React.Component{
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"progress slider horizontal "+this.props.play_state} onClick={ (e) => this.handleClick(e) } >
|
||||
<div className={"progress slider horizontal "+this.props.play_state}>
|
||||
<div className="track">
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={percent}
|
||||
onChange={e => this.handleChange(parseInt(e.target.value))}
|
||||
/>
|
||||
<div className="progress" style={{ width: (percent)+'%' }}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,52 +1,19 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import Icon from '../Icon'
|
||||
import React from 'react';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import * as helpers from '../../helpers';
|
||||
|
||||
export default class VolumeControl extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.handleChange = helpers.throttle(this.handleChange.bind(this), 100);
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
var old_percent = this.props.volume;
|
||||
var slider = e.target;
|
||||
if (slider.className != 'slider' ) slider = slider.parentElement;
|
||||
|
||||
var sliderX = e.clientX - slider.getBoundingClientRect().left;
|
||||
var sliderWidth = slider.getBoundingClientRect().width;
|
||||
var percent = Math.round((sliderX / sliderWidth ) * 100);
|
||||
|
||||
if (percent > 100){
|
||||
percent = 100
|
||||
} else if (percent < 0){
|
||||
percent = 0
|
||||
}
|
||||
|
||||
this.props.onVolumeChange(percent, old_percent);
|
||||
}
|
||||
|
||||
handleWheel(e){
|
||||
if (this.props.scrollWheel){
|
||||
var old_percent = this.props.volume;
|
||||
|
||||
// Identify which direction we've scrolled (inverted)
|
||||
// This is simplified and doesn't consider momentum as it varies wildly
|
||||
// between browsers and devices
|
||||
var direction = (e.deltaY > 0 ? -1 : 1)
|
||||
var percent = this.props.volume;
|
||||
|
||||
percent += direction * 5
|
||||
|
||||
if (percent > 100){
|
||||
percent = 100
|
||||
} else if (percent < 0){
|
||||
percent = 0
|
||||
}
|
||||
|
||||
this.props.onVolumeChange(percent, old_percent);
|
||||
e.preventDefault();
|
||||
}
|
||||
handleChange(value){
|
||||
this.props.onVolumeChange(value, this.props.volume);
|
||||
}
|
||||
|
||||
renderMuteButton(){
|
||||
@ -77,10 +44,17 @@ export default class VolumeControl extends React.Component{
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={className} onWheel={e => this.handleWheel(e)}>
|
||||
<span className={className}>
|
||||
{this.props.NoMuteButton ? null : this.renderMuteButton()}
|
||||
<div className="slider-wrapper">
|
||||
<div className="slider horizontal" onClick={e => this.handleClick(e)}>
|
||||
<div className="slider horizontal">
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="25"
|
||||
value={this.props.volume/4}
|
||||
onChange={e => this.handleChange(parseInt(e.target.value)*4)}
|
||||
/>
|
||||
<div className="track">
|
||||
<div className="progress" style={{ width: this.props.volume+'%' }}></div>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,47 @@ export let isTouchDevice = function(){
|
||||
return 'ontouchstart' in document.documentElement
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function, that, as long as it continues to be invoked, will not
|
||||
* be triggered. The function will be called after it stops being called for
|
||||
* N milliseconds. If `immediate` is passed, trigger the function on the
|
||||
* leading edge, instead of the trailing.
|
||||
**/
|
||||
export let debounce = function(fn, wait, immediate){
|
||||
var timeout;
|
||||
return function(){
|
||||
var context = this, args = arguments;
|
||||
|
||||
var later = function(){
|
||||
timeout = null;
|
||||
if (!immediate){
|
||||
fn.apply(context, args);
|
||||
}
|
||||
};
|
||||
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
|
||||
if (callNow){
|
||||
fn.apply(context, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export let throttle = function(fn, delay){
|
||||
let lastCall = 0;
|
||||
return function (...args){
|
||||
const now = (new Date).getTime();
|
||||
if (now - lastCall < delay) {
|
||||
return;
|
||||
}
|
||||
lastCall = now;
|
||||
return fn(...args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Storage handler
|
||||
|
||||
@ -278,7 +278,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +(store.getState().mopidy.play_state == 'paused' ? ' resumed' : ' started')+' playback',
|
||||
icon: (store.getState().core.current_track ? helpers.getTrackIcon(store.getState().core.current_track, store.getState().core) : false)
|
||||
}
|
||||
@ -301,7 +300,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' paused playback',
|
||||
icon: (store.getState().core.current_track ? helpers.getTrackIcon(store.getState().core.current_track, store.getState().core) : false)
|
||||
}
|
||||
@ -320,7 +318,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' skipped <em>'+store.getState().core.current_track.name+'</em>',
|
||||
icon: (store.getState().core.current_track ? helpers.getTrackIcon(store.getState().core.current_track, store.getState().core) : false)
|
||||
}
|
||||
@ -338,7 +335,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' stopped playback',
|
||||
icon: (store.getState().core.current_track ? helpers.getTrackIcon(store.getState().core.current_track, store.getState().core) : false)
|
||||
}
|
||||
@ -353,7 +349,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' changed track'
|
||||
}
|
||||
}
|
||||
@ -366,7 +361,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' removed '+action.tlids.length+' tracks'
|
||||
}
|
||||
}
|
||||
@ -439,7 +433,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +(action.mute ? ' muted' : ' unmuted')+' playback'
|
||||
}
|
||||
}
|
||||
@ -599,7 +592,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' is adding '+action.uris.length+' URIs to queue',
|
||||
icon: (store.getState().core.current_track ? helpers.getTrackIcon(store.getState().core.current_track, store.getState().core) : false)
|
||||
}
|
||||
@ -821,7 +813,6 @@ const MopidyMiddleware = (function(){
|
||||
'notification',
|
||||
{
|
||||
notification: {
|
||||
type: 'info',
|
||||
content: store.getState().pusher.username +' cleared queue'
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,32 @@
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
input[type="range"]{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
width: 1px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 1px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-ms-thumb {
|
||||
width: 1px;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.track {
|
||||
position: absolute;
|
||||
background: rgba(0,0,0,0.2);
|
||||
@ -37,6 +63,34 @@
|
||||
top: 0;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
border-radius: 4px;
|
||||
|
||||
&:after {
|
||||
@include animate(0.1s);
|
||||
content: '';
|
||||
display: block;
|
||||
background: $turquoise;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -1px;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.track {
|
||||
.progress {
|
||||
&:after {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
top: -4px;
|
||||
right: -6px;
|
||||
background: lighten($turquoise, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user