Splitting out mute, cleaning up mobile output controls
This commit is contained in:
@ -4445,7 +4445,7 @@ $icon-websocket: \e920;
|
|||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 20px; }
|
height: 20px; }
|
||||||
.slider input[type="range"] {
|
.slider__input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -4454,16 +4454,16 @@ $icon-websocket: \e920;
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
.slider input[type="range"]::-webkit-slider-thumb {
|
.slider__input::-webkit-slider-thumb {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
border: 0; }
|
border: 0; }
|
||||||
.slider input[type="range"]::-moz-range-thumb {
|
.slider__input::-moz-range-thumb {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
border: 0; }
|
border: 0; }
|
||||||
.slider input[type="range"]::-ms-thumb {
|
.slider__input::-ms-thumb {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
border: 0; }
|
border: 0; }
|
||||||
.slider .track {
|
.slider__track {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@ -4472,7 +4472,7 @@ $icon-websocket: \e920;
|
|||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
margin-top: -3px; }
|
margin-top: -3px; }
|
||||||
.slider .track .progress {
|
.slider__track__progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #08d58f;
|
background: #08d58f;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -4482,7 +4482,7 @@ $icon-websocket: \e920;
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border-radius: 4px; }
|
border-radius: 4px; }
|
||||||
.slider .track .progress:after {
|
.slider__track__progress:after {
|
||||||
-webkit-transition: all 0.1s ease-in-out;
|
-webkit-transition: all 0.1s ease-in-out;
|
||||||
-moz-transition: all 0.1s ease-in-out;
|
-moz-transition: all 0.1s ease-in-out;
|
||||||
-o-transition: all 0.1s ease-in-out;
|
-o-transition: all 0.1s ease-in-out;
|
||||||
@ -4496,11 +4496,11 @@ $icon-websocket: \e920;
|
|||||||
width: 4px;
|
width: 4px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
border-radius: 50%; }
|
border-radius: 50%; }
|
||||||
.slider.disabled .progress {
|
.slider--disabled .slider__track__progress, .slider--muted .slider__track__progress {
|
||||||
background: #a3a19f; }
|
background: #a3a19f; }
|
||||||
.slider.disabled .progress:after {
|
.slider--disabled .slider__track__progress:after, .slider--muted .slider__track__progress:after {
|
||||||
background: #a3a19f !important; }
|
background: #a3a19f !important; }
|
||||||
.slider:hover .track .progress:after {
|
.slider:hover .slider__track__progress:after {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
@ -4684,15 +4684,11 @@ $icon-websocket: \e920;
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
width: 150px;
|
width: 150px;
|
||||||
font-size: 18px; }
|
font-size: 18px; }
|
||||||
.playback-controls section.volume .modal-trigger {
|
.playback-controls section.volume .slider__wrapper {
|
||||||
display: none; }
|
|
||||||
.playback-controls section.volume .slider-wrapper {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 6px;
|
bottom: 6px;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: 30px; }
|
left: 30px; }
|
||||||
.playback-controls section.volume .muted .slider .progress {
|
|
||||||
background: #a3a19f; }
|
|
||||||
.playback-controls section.triggers {
|
.playback-controls section.triggers {
|
||||||
display: none; }
|
display: none; }
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
@ -4700,8 +4696,8 @@ $icon-websocket: \e920;
|
|||||||
width: auto;
|
width: auto;
|
||||||
bottom: auto;
|
bottom: auto;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
left: 70px;
|
left: 80px;
|
||||||
right: 70px;
|
right: 80px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #FFFFFF !important; }
|
color: #FFFFFF !important; }
|
||||||
@ -4743,20 +4739,29 @@ $icon-websocket: \e920;
|
|||||||
height: 150px; }
|
height: 150px; }
|
||||||
.playback-controls.expanded section.settings {
|
.playback-controls.expanded section.settings {
|
||||||
display: block;
|
display: block;
|
||||||
right: 20px;
|
right: 0;
|
||||||
bottom: 60px;
|
bottom: 100px;
|
||||||
text-align: right; }
|
text-align: right; }
|
||||||
.playback-controls.expanded section.volume {
|
.playback-controls.expanded section.volume {
|
||||||
width: auto;
|
width: auto;
|
||||||
display: block;
|
display: block;
|
||||||
right: 130px;
|
right: 110px;
|
||||||
left: 22px;
|
left: 22px;
|
||||||
bottom: 60px; }
|
bottom: 100px; }
|
||||||
.playback-controls.expanded section.progress {
|
.playback-controls.expanded section.progress {
|
||||||
display: block;
|
display: block;
|
||||||
bottom: 110px;
|
bottom: 55px;
|
||||||
left: 0;
|
left: -10px;
|
||||||
right: 0; } }
|
right: -10px; }
|
||||||
|
.playback-controls.expanded .output-control {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 150px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px; }
|
||||||
|
.playback-controls.expanded .output-control > .control {
|
||||||
|
display: none; }
|
||||||
|
.playback-controls.expanded .output-control__items {
|
||||||
|
width: 100%; } }
|
||||||
|
|
||||||
.output-control {
|
.output-control {
|
||||||
position: relative; }
|
position: relative; }
|
||||||
@ -4798,8 +4803,6 @@ $icon-websocket: \e920;
|
|||||||
position: relative; }
|
position: relative; }
|
||||||
.output-control__item:not(:first-child) {
|
.output-control__item:not(:first-child) {
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.05); }
|
border-top: 1px solid rgba(0, 0, 0, 0.05); }
|
||||||
.output-control__item--has-power-button {
|
|
||||||
padding-left: 56px; }
|
|
||||||
.output-control__item__actions {
|
.output-control__item__actions {
|
||||||
float: right; }
|
float: right; }
|
||||||
.output-control__item__actions .action {
|
.output-control__item__actions .action {
|
||||||
@ -4811,16 +4814,56 @@ $icon-websocket: \e920;
|
|||||||
color: #a3a19f; }
|
color: #a3a19f; }
|
||||||
.output-control__item__actions .action:hover {
|
.output-control__item__actions .action:hover {
|
||||||
color: #181818; }
|
color: #181818; }
|
||||||
|
.output-control__item--has-power-button .output-control__item__volume {
|
||||||
|
padding-left: 50px; }
|
||||||
|
.output-control__item__volume {
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-left: 25px; }
|
||||||
|
.output-control__item__mute.control {
|
||||||
|
position: relative;
|
||||||
|
padding: 2px;
|
||||||
|
color: #000000;
|
||||||
|
float: left;
|
||||||
|
font-size: 16px; }
|
||||||
|
|
||||||
|
@keyframes click_feedback {
|
||||||
|
0% {
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 100%;
|
||||||
|
opacity: 1; }
|
||||||
|
100% {
|
||||||
|
top: 25%;
|
||||||
|
left: -25%;
|
||||||
|
width: 150%;
|
||||||
|
padding-bottom: 150%;
|
||||||
|
opacity: 0; } }
|
||||||
|
.output-control__item__mute.control:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-top: -50%;
|
||||||
|
pointer-events: none; }
|
||||||
|
.output-control__item__mute.control:focus:after, .output-control__item__mute.control:active:after {
|
||||||
|
animation-name: click_feedback;
|
||||||
|
animation-duration: 0.2s;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
animation-iteration-count: 1; }
|
||||||
.output-control__item__power {
|
.output-control__item__power {
|
||||||
position: relative;
|
position: relative;
|
||||||
position: absolute !important;
|
width: 18px;
|
||||||
top: 12px;
|
height: 18px;
|
||||||
left: 12px;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
cursor: pointer; }
|
cursor: pointer;
|
||||||
|
float: left;
|
||||||
|
margin-top: -2px;
|
||||||
|
margin-right: 6px; }
|
||||||
|
|
||||||
@keyframes click_feedback {
|
@keyframes click_feedback {
|
||||||
0% {
|
0% {
|
||||||
@ -4851,13 +4894,13 @@ $icon-websocket: \e920;
|
|||||||
animation-timing-function: ease-out;
|
animation-timing-function: ease-out;
|
||||||
animation-iteration-count: 1; }
|
animation-iteration-count: 1; }
|
||||||
.output-control__item__power .icon {
|
.output-control__item__power .icon {
|
||||||
padding-top: 10px;
|
padding-top: 5px;
|
||||||
font-size: 16px; }
|
font-size: 12px; }
|
||||||
.output-control__item__power:before {
|
.output-control__item__power:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px;
|
top: 2px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-bottom: 100%;
|
padding-bottom: 100%;
|
||||||
@ -4865,46 +4908,6 @@ $icon-websocket: \e920;
|
|||||||
z-index: -1;
|
z-index: -1;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
opacity: 1; }
|
opacity: 1; }
|
||||||
.output-control__item__volume {
|
|
||||||
position: relative;
|
|
||||||
padding-left: 22px;
|
|
||||||
display: block; }
|
|
||||||
.output-control__item__volume .mute-control {
|
|
||||||
position: relative;
|
|
||||||
position: absolute !important;
|
|
||||||
top: -2px;
|
|
||||||
left: -2px;
|
|
||||||
padding: 2px;
|
|
||||||
color: #000000; }
|
|
||||||
|
|
||||||
@keyframes click_feedback {
|
|
||||||
0% {
|
|
||||||
top: 50%;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 100%;
|
|
||||||
opacity: 1; }
|
|
||||||
100% {
|
|
||||||
top: 25%;
|
|
||||||
left: -25%;
|
|
||||||
width: 150%;
|
|
||||||
padding-bottom: 150%;
|
|
||||||
opacity: 0; } }
|
|
||||||
.output-control__item__volume .mute-control:after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
z-index: 1;
|
|
||||||
opacity: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-top: -50%;
|
|
||||||
pointer-events: none; }
|
|
||||||
.output-control__item__volume .mute-control:focus:after, .output-control__item__volume .mute-control:active:after {
|
|
||||||
animation-name: click_feedback;
|
|
||||||
animation-duration: 0.2s;
|
|
||||||
animation-timing-function: ease-out;
|
|
||||||
animation-iteration-count: 1; }
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.output-control__items {
|
.output-control__items {
|
||||||
width: 86vw;
|
width: 86vw;
|
||||||
@ -6155,13 +6158,13 @@ main header {
|
|||||||
width: 1px;
|
width: 1px;
|
||||||
background: #383734;
|
background: #383734;
|
||||||
z-index: 0; }
|
z-index: 0; }
|
||||||
.snapcast__client__latency .latency-control .progress.positive {
|
.snapcast__client__latency .latency-control .slider__track__progress--positive {
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0; }
|
border-bottom-left-radius: 0; }
|
||||||
.snapcast__client__latency .latency-control .progress.negative {
|
.snapcast__client__latency .latency-control .slider__track__progress--negative {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-bottom-right-radius: 0; }
|
border-bottom-right-radius: 0; }
|
||||||
.snapcast__client__latency .latency-control .progress.negative:after {
|
.snapcast__client__latency .latency-control .slider__track__progress--negative:after {
|
||||||
right: auto;
|
right: auto;
|
||||||
left: -1px; }
|
left: -1px; }
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
// Release details
|
// Release details
|
||||||
// These are automatically injected to built HTML
|
// These are automatically injected to built HTML
|
||||||
var build = "1538382441";
|
var build = "1538419845";
|
||||||
var version = "3.26.2";
|
var version = "3.26.2";
|
||||||
|
|
||||||
// Construct the script tag
|
// Construct the script tag
|
||||||
|
|||||||
@ -48,18 +48,19 @@ export default class LatencyControl extends React.Component{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="latency-control">
|
<span className="latency-control">
|
||||||
<div className="slider-wrapper">
|
<div className="slider__wrapper">
|
||||||
<div className="slider horizontal">
|
<div className="slider slider--latency">
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="-100"
|
min="-100"
|
||||||
max="100"
|
max="100"
|
||||||
|
className="slider__input"
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
onChange={e => this.handleChange(parseInt(e.target.value))}
|
onChange={e => this.handleChange(parseInt(e.target.value))}
|
||||||
/>
|
/>
|
||||||
<div className="zero"></div>
|
<div className="zero"></div>
|
||||||
<div className="track">
|
<div className="slider__track">
|
||||||
<div className={"progress "+(negative ? 'negative' : 'positive')} style={{ width: width+'%', left: left+'%' }}></div>
|
<div className={"slider__track__progress slider__track__progress--"+(negative ? 'negative' : 'positive')} style={{ width: width+'%', left: left+'%' }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
30
src/js/components/Fields/MuteControl.js
Executable file
30
src/js/components/Fields/MuteControl.js
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Icon from '../Icon';
|
||||||
|
import * as helpers from '../../helpers';
|
||||||
|
|
||||||
|
export default class MuteControl extends React.Component{
|
||||||
|
|
||||||
|
constructor(props){
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(){
|
||||||
|
if (this.props.mute){
|
||||||
|
return (
|
||||||
|
<a className={"control mute-control "+(this.props.noTooltip ? "" : "tooltip ")+(this.props.className ? this.props.className : "")} onClick={() => this.props.onMuteChange(false)}>
|
||||||
|
<Icon className="red-text" name="volume_off" />
|
||||||
|
{this.props.noTooltip ? null : <span className="tooltip__content">Unmute</span>}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<a className={"control mute-control "+(this.props.noTooltip ? "" : "tooltip ")+(this.props.className ? this.props.className : "")} onClick={() => this.props.onMuteChange(true)}>
|
||||||
|
<Icon className="muted" name="volume_mute" />
|
||||||
|
{this.props.noTooltip ? null : <span className="tooltip__content">Mute</span>}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import { connect } from 'react-redux'
|
|||||||
import { bindActionCreators } from 'redux'
|
import { bindActionCreators } from 'redux'
|
||||||
|
|
||||||
import VolumeControl from './VolumeControl'
|
import VolumeControl from './VolumeControl'
|
||||||
|
import MuteControl from './MuteControl'
|
||||||
import SnapcastPowerButton from './SnapcastPowerButton'
|
import SnapcastPowerButton from './SnapcastPowerButton'
|
||||||
import Icon from '../Icon'
|
import Icon from '../Icon'
|
||||||
|
|
||||||
@ -73,21 +74,28 @@ class OutputControl extends React.Component{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"output-control__item outputs__item--snapcast"+(commands && commands.power ? " output-control__item--has-power-button": '')} key={client.id}>
|
<div className={"output-control__item outputs__item--snapcast"+(commands && commands.power ? " output-control__item--has-power-button": '')} key={client.id}>
|
||||||
{commands && commands.power ? <SnapcastPowerButton
|
|
||||||
className="output-control__item__power"
|
|
||||||
client={client}
|
|
||||||
onClick={e => this.props.snapcastActions.sendClientCommand(client.id, commands.power)}
|
|
||||||
/> : null}
|
|
||||||
<div className="output-control__item__name">
|
<div className="output-control__item__name">
|
||||||
{client.name}
|
{client.name}
|
||||||
</div>
|
</div>
|
||||||
<VolumeControl
|
<div className="output-control__item__controls">
|
||||||
className="output-control__item__volume"
|
{commands && commands.power ? <SnapcastPowerButton
|
||||||
volume={client.volume}
|
className="output-control__item__power"
|
||||||
mute={client.mute}
|
client={client}
|
||||||
onVolumeChange={percent => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
onClick={e => this.props.snapcastActions.sendClientCommand(client.id, commands.power)}
|
||||||
onMuteChange={mute => this.props.snapcastActions.setClientMute(client.id, mute)}
|
/> : null}
|
||||||
/>
|
<MuteControl
|
||||||
|
className="output-control__item__mute"
|
||||||
|
noTooltip={true}
|
||||||
|
mute={client.mute}
|
||||||
|
onMuteChange={mute => this.props.snapcastActions.setClientMute(client.id, mute)}
|
||||||
|
/>
|
||||||
|
<VolumeControl
|
||||||
|
className="output-control__item__volume"
|
||||||
|
volume={client.volume}
|
||||||
|
mute={client.mute}
|
||||||
|
onVolumeChange={percent => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -138,7 +146,7 @@ class OutputControl extends React.Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
if (this.state.expanded){
|
if (this.state.expanded || this.props.force_expanded){
|
||||||
return (
|
return (
|
||||||
<span className="output-control">
|
<span className="output-control">
|
||||||
<a className="control speakers active" onClick={e => this.setExpanded()}><Icon name="speaker" /></a>
|
<a className="control speakers active" onClick={e => this.setExpanded()}><Icon name="speaker" /></a>
|
||||||
|
|||||||
@ -29,16 +29,17 @@ class ProgressSlider extends React.Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"progress slider horizontal "+this.props.play_state}>
|
<div className={"slider slider--playback-progress slider--"+this.props.play_state}>
|
||||||
<div className="track">
|
<div className="slider__track">
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
value={percent}
|
value={percent}
|
||||||
|
className="slider__input"
|
||||||
onChange={e => this.handleChange(parseInt(e.target.value))}
|
onChange={e => this.handleChange(parseInt(e.target.value))}
|
||||||
/>
|
/>
|
||||||
<div className="progress" style={{ width: (percent)+'%' }}></div>
|
<div className="slider__track__progress" style={{ width: (percent)+'%' }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -16,51 +16,23 @@ export default class VolumeControl extends React.Component{
|
|||||||
this.props.onVolumeChange(value, this.props.volume);
|
this.props.onVolumeChange(value, this.props.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMuteButton(){
|
|
||||||
if (this.props.mute){
|
|
||||||
return (
|
|
||||||
<a className="control mute-control tooltip" onClick={() => this.props.onMuteChange(false)}>
|
|
||||||
<Icon className="red-text" name="volume_off" />
|
|
||||||
<span className="tooltip__content">Unmute</span>
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<a className="control mute-control tooltip" onClick={() => this.props.onMuteChange(true)}>
|
|
||||||
<Icon className="muted" name="volume_mute" />
|
|
||||||
<span className="tooltip__content">Mute</span>
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
var className = "volume-control";
|
|
||||||
if (this.props.mute){
|
|
||||||
className += " muted";
|
|
||||||
}
|
|
||||||
if (this.props.className){
|
|
||||||
className += " "+this.props.className;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={className}>
|
<div className={"slider__wrapper "+(this.props.className ? this.props.className : "")}>
|
||||||
{this.props.NoMuteButton ? null : this.renderMuteButton()}
|
<div className={"slider slider--volume "+(this.props.mute ? "slider--muted" : "")}>
|
||||||
<div className="slider-wrapper">
|
<input
|
||||||
<div className={"slider horizontal"+(this.props.mute ? " disabled" : "")}>
|
className="slider__input"
|
||||||
<input
|
type="range"
|
||||||
type="range"
|
min="0"
|
||||||
min="0"
|
max="25"
|
||||||
max="25"
|
value={this.props.volume/4}
|
||||||
value={this.props.volume/4}
|
onChange={e => this.handleChange(parseInt(e.target.value)*4)}
|
||||||
onChange={e => this.handleChange(parseInt(e.target.value)*4)}
|
/>
|
||||||
/>
|
<div className="slider__track">
|
||||||
<div className="track">
|
<div className="slider__track__progress" style={{ width: this.props.volume+'%' }}></div>
|
||||||
<div className="progress" style={{ width: this.props.volume+'%' }}></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { bindActionCreators } from 'redux'
|
|||||||
|
|
||||||
import ProgressSlider from './Fields/ProgressSlider'
|
import ProgressSlider from './Fields/ProgressSlider'
|
||||||
import VolumeControl from './Fields/VolumeControl'
|
import VolumeControl from './Fields/VolumeControl'
|
||||||
|
import MuteControl from './Fields/MuteControl'
|
||||||
import OutputControl from './Fields/OutputControl'
|
import OutputControl from './Fields/OutputControl'
|
||||||
import Dater from './Dater'
|
import Dater from './Dater'
|
||||||
import ArtistSentence from './ArtistSentence'
|
import ArtistSentence from './ArtistSentence'
|
||||||
@ -161,7 +162,7 @@ class PlaybackControls extends React.Component{
|
|||||||
{this.renderConsumeButton()}
|
{this.renderConsumeButton()}
|
||||||
{this.renderRandomButton()}
|
{this.renderRandomButton()}
|
||||||
{this.renderRepeatButton()}
|
{this.renderRepeatButton()}
|
||||||
<OutputControl />
|
<OutputControl force_expanded={this.state.expanded} />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="progress">
|
<section className="progress">
|
||||||
@ -171,12 +172,15 @@ class PlaybackControls extends React.Component{
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="volume">
|
<section className="volume">
|
||||||
|
<MuteControl
|
||||||
|
mute={this.props.mute}
|
||||||
|
onMuteChange={mute => this.props.mopidyActions.setMute(mute)}
|
||||||
|
/>
|
||||||
<VolumeControl
|
<VolumeControl
|
||||||
scrollWheel
|
scrollWheel
|
||||||
volume={this.props.volume}
|
volume={this.props.volume}
|
||||||
mute={this.props.mute}
|
mute={this.props.mute}
|
||||||
onVolumeChange={percent => this.props.mopidyActions.setVolume(percent)}
|
onVolumeChange={percent => this.props.mopidyActions.setVolume(percent)}
|
||||||
onMuteChange={mute => this.props.mopidyActions.setMute(mute)}
|
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
1
src/scss/components/_mute-control.scss
Executable file
1
src/scss/components/_mute-control.scss
Executable file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
@ -53,10 +53,6 @@
|
|||||||
border-top: 1px solid rgba(0,0,0,0.05);
|
border-top: 1px solid rgba(0,0,0,0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
&--has-power-button {
|
|
||||||
padding-left: 56px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__actions {
|
&__actions {
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
@ -71,27 +67,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--has-power-button {
|
||||||
|
.output-control__item__volume {
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__volume {
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__mute.control {
|
||||||
|
@include click_feedback(rgba(0,0,0,0.5));
|
||||||
|
padding: 2px;
|
||||||
|
color: $black;
|
||||||
|
float: left;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
&__power {
|
&__power {
|
||||||
@include click_feedback(rgba(0,0,0,0.5));
|
@include click_feedback(rgba(0,0,0,0.5));
|
||||||
position: absolute !important;
|
width: 18px;
|
||||||
top: 12px;
|
height: 18px;
|
||||||
left: 12px;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $white;
|
color: $white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
float: left;
|
||||||
|
margin-top: -2px;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
padding-top: 10px;
|
padding-top: 5px;
|
||||||
font-size: 16px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px;
|
top: 2px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-bottom: 100%;
|
padding-bottom: 100%;
|
||||||
@ -101,21 +116,6 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__volume {
|
|
||||||
position: relative;
|
|
||||||
padding-left: 22px;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.mute-control {
|
|
||||||
@include click_feedback(rgba(0,0,0,0.5));
|
|
||||||
position: absolute !important;
|
|
||||||
top: -2px;
|
|
||||||
left: -2px;
|
|
||||||
padding: 2px;
|
|
||||||
color: $black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@include responsive($bp_medium){
|
@include responsive($bp_medium){
|
||||||
|
|||||||
@ -176,22 +176,12 @@
|
|||||||
width: 150px;
|
width: 150px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
||||||
.modal-trigger {
|
.slider__wrapper {
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-wrapper {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 6px;
|
bottom: 6px;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: 30px;
|
left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.muted {
|
|
||||||
.slider .progress {
|
|
||||||
background: $mid_grey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.triggers {
|
&.triggers {
|
||||||
@ -205,8 +195,8 @@
|
|||||||
width: auto;
|
width: auto;
|
||||||
bottom: auto;
|
bottom: auto;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
left: 70px;
|
left: 80px;
|
||||||
right: 70px;
|
right: 80px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: $white !important;
|
color: $white !important;
|
||||||
@ -277,27 +267,41 @@
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
|
|
||||||
section {
|
section {
|
||||||
|
|
||||||
&.settings {
|
&.settings {
|
||||||
display: block;
|
display: block;
|
||||||
right: 20px;
|
right: 0;
|
||||||
bottom: 60px;
|
bottom: 100px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.volume {
|
&.volume {
|
||||||
width: auto;
|
width: auto;
|
||||||
display: block;
|
display: block;
|
||||||
right: 130px;
|
right: 110px;
|
||||||
left: 22px;
|
left: 22px;
|
||||||
bottom: 60px;
|
bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.progress {
|
&.progress {
|
||||||
display: block;
|
display: block;
|
||||||
bottom: 110px;
|
bottom: 55px;
|
||||||
left: 0;
|
left: -10px;
|
||||||
right: 0;
|
right: -10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-control {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 150px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
& > .control {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__items {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|
||||||
input[type="range"]{
|
&__input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.track {
|
&__track {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(0,0,0,0.2);
|
background: rgba(0,0,0,0.2);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@ -40,7 +40,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
|
|
||||||
.progress {
|
&__progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: $turquoise;
|
background: $turquoise;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -66,8 +66,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&--disabled,
|
||||||
.progress {
|
&--muted {
|
||||||
|
.slider__track__progress {
|
||||||
background: $mid_grey;
|
background: $mid_grey;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
@ -77,8 +78,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.track {
|
.slider__track {
|
||||||
.progress {
|
&__progress {
|
||||||
&:after {
|
&:after {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
|
|||||||
@ -145,18 +145,22 @@
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress.positive {
|
.slider__track {
|
||||||
border-top-left-radius: 0;
|
&__progress {
|
||||||
border-bottom-left-radius: 0;
|
&--positive {
|
||||||
}
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.progress.negative {
|
&--negative {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
right: auto;
|
right: auto;
|
||||||
left: -1px;
|
left: -1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user