Latency limit 150; Label wrappers for text fields; Detecting image changes in playback controller
This commit is contained in:
@ -6,8 +6,7 @@ import * as helpers from '../../helpers';
|
||||
export default class LatencyControl extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
super(props);
|
||||
this.handleChange = helpers.throttle(this.handleChange.bind(this), 100);
|
||||
}
|
||||
|
||||
@ -28,7 +27,7 @@ export default class LatencyControl extends React.Component{
|
||||
var width = percentage;
|
||||
var negative = false;
|
||||
|
||||
if (width > 50) width = 50;
|
||||
if (width > (this.props.max / 2)) width = this.props.max / 2;
|
||||
|
||||
// Negative value
|
||||
// We reverse it to a positive for easier maths and style rules
|
||||
@ -43,7 +42,7 @@ export default class LatencyControl extends React.Component{
|
||||
var negative = true;
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (width > 50) width = 50;
|
||||
if (width > (this.props.max / 2)) width = this.props.max / 2;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -52,8 +51,8 @@ export default class LatencyControl extends React.Component{
|
||||
<div className="slider slider--latency">
|
||||
<input
|
||||
type="range"
|
||||
min="-100"
|
||||
max="100"
|
||||
min={-(this.props.max)}
|
||||
max={this.props.max}
|
||||
className="slider__input"
|
||||
value={this.props.value}
|
||||
onChange={e => this.handleChange(parseInt(e.target.value))}
|
||||
|
||||
@ -92,15 +92,25 @@ class PlaybackControls extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
// Started a track or changed to no track
|
||||
if ((!this.props.current_track && nextProps.current_track) || (this.props.current_track && !nextProps.current_track)){
|
||||
console.log("One was null, the other wasn't", {old: this.props.current_track, next: nextProps.current_track});
|
||||
this.setState({current_track: nextProps.current_track});
|
||||
}
|
||||
|
||||
// Direct swap-out of a track (with no 'null' intermediate state)
|
||||
// This is precautionary and I've never been able to trigger it, but it's a good safety
|
||||
if (this.props.current_track && nextProps.current_track && this.props.current_track.uri !== nextProps.current_track.uri){
|
||||
console.log("URI different", {old: this.props.current_track.uri, next: nextProps.current_track.uri});
|
||||
this.setState({current_track: nextProps.current_track});
|
||||
}
|
||||
|
||||
// Images have just loaded
|
||||
// A bit niggly to have to deeply check this...
|
||||
if (this.props.current_track && nextProps.current_track){
|
||||
|
||||
if ((this.props.current_track.images && !nextProps.current_track.images) || (!this.props.current_track.images && nextProps.current_track.images)){
|
||||
this.setState({current_track: nextProps.current_track});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleTouchStart(e){
|
||||
|
||||
@ -105,7 +105,7 @@ class Services extends React.Component{
|
||||
return (
|
||||
<div>
|
||||
{not_installed}
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Country</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -118,8 +118,8 @@ class Services extends React.Component{
|
||||
An <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2" target="_blank">ISO 3166-1 alpha-2</a> country code (eg <em>NZ</em>)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
</label>
|
||||
<label className="field">
|
||||
<div className="name">Locale</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -132,7 +132,7 @@ class Services extends React.Component{
|
||||
Lowercase <a href="http://en.wikipedia.org/wiki/ISO_639" target="_blank">ISO 639 language code</a> and an uppercase <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2" target="_blank">ISO 3166-1 alpha-2 country code</a>, joined by an underscore (eg <em>en_NZ</em>)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div className="field current-user">
|
||||
<div className="name">Current user</div>
|
||||
@ -258,7 +258,7 @@ class Services extends React.Component{
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Location</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -269,7 +269,7 @@ class Services extends React.Component{
|
||||
The full URL to your stream endpoint
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ class Snapcast extends React.Component{
|
||||
<div className="list snapcast__clients">
|
||||
{
|
||||
clients.map(client => {
|
||||
var class_name = "list__item snapcast__client";
|
||||
var class_name = "list__item list__item--no-interaction snapcast__client";
|
||||
if (client.connected){
|
||||
class_name += " snapcast__client--connected";
|
||||
} else {
|
||||
@ -98,7 +98,7 @@ class Snapcast extends React.Component{
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__details">
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
@ -108,8 +108,8 @@ class Snapcast extends React.Component{
|
||||
value={client.name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field dropdown">
|
||||
</label>
|
||||
<label className="field dropdown">
|
||||
<div className="name">
|
||||
Group
|
||||
</div>
|
||||
@ -129,7 +129,7 @@ class Snapcast extends React.Component{
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div className="snapcast__client__volume field">
|
||||
<div className="name">
|
||||
Volume
|
||||
@ -153,7 +153,7 @@ class Snapcast extends React.Component{
|
||||
</div>
|
||||
<div className="input">
|
||||
<LatencyControl
|
||||
max="100"
|
||||
max="150"
|
||||
value={client.latency}
|
||||
onChange={value => this.props.snapcastActions.setClientLatency(client.id, parseInt(value))}
|
||||
/>
|
||||
|
||||
@ -126,7 +126,7 @@ class Debug extends React.Component{
|
||||
</form>
|
||||
|
||||
<h4 className="underline">Spotify</h4>
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Access token</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -134,11 +134,11 @@ class Debug extends React.Component{
|
||||
onChange={e => this.props.spotifyActions.authorizationGranted({access_token: e.target.value})}
|
||||
value={this.state.access_token} />
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<h4 className="underline">Mopidy</h4>
|
||||
<form onSubmit={(e) => this.callMopidy(e)}>
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Call</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -146,8 +146,8 @@ class Debug extends React.Component{
|
||||
onChange={ e => this.setState({ mopidy_call: e.target.value })}
|
||||
value={ this.state.mopidy_call } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
</label>
|
||||
<label className="field">
|
||||
<div className="name">Data</div>
|
||||
<div className="input">
|
||||
<textarea
|
||||
@ -155,7 +155,7 @@ class Debug extends React.Component{
|
||||
value={ this.state.mopidy_data }>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div className="field">
|
||||
<div className="name"></div>
|
||||
<div className="input">
|
||||
@ -166,7 +166,7 @@ class Debug extends React.Component{
|
||||
|
||||
<h4 className="underline">Pusher</h4>
|
||||
<form onSubmit={(e) => this.callPusher(e)}>
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Examples</div>
|
||||
<div className="input">
|
||||
<select onChange={ e => this.setState({ pusher_data: e.target.value })}>
|
||||
@ -183,8 +183,8 @@ class Debug extends React.Component{
|
||||
<option value='{"method":"perform_upgrade"}'>Perform upgrade (beta)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
</label>
|
||||
<label className="field">
|
||||
<div className="name">Data</div>
|
||||
<div className="input">
|
||||
<textarea
|
||||
@ -192,7 +192,7 @@ class Debug extends React.Component{
|
||||
value={ this.state.pusher_data }>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div className="field">
|
||||
<div className="name"></div>
|
||||
<div className="input">
|
||||
@ -212,13 +212,6 @@ class Debug extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export our component
|
||||
*
|
||||
* We also integrate our global store, using connect()
|
||||
**/
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
connection_id: state.pusher.connection_id,
|
||||
|
||||
@ -167,7 +167,7 @@ class Settings extends React.Component {
|
||||
{
|
||||
commands.map(command => {
|
||||
return (
|
||||
<div className="list__item commands-setup__item no-click" key={command.id}>
|
||||
<div className="list__item commands-setup__item list__item--no-interaction" key={command.id}>
|
||||
<div className="col col--w90">
|
||||
<div className="commands__item commands__item--interactive" onClick={e => this.props.pusherActions.sendCommand(command.id, true)}>
|
||||
<Icon className="commands__item__icon" name={command.icon} />
|
||||
@ -223,7 +223,7 @@ class Settings extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Username</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -236,10 +236,10 @@ class Settings extends React.Component {
|
||||
A non-unique string used to identify this client (no special characters)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<form onSubmit={(e) => this.setConfig(e)}>
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Host</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -249,8 +249,8 @@ class Settings extends React.Component {
|
||||
onBlur={e => this.setState({input_in_focus: null})}
|
||||
value={ this.state.mopidy_host } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
</label>
|
||||
<label className="field">
|
||||
<div className="name">Port</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -260,7 +260,7 @@ class Settings extends React.Component {
|
||||
onBlur={e => this.setState({input_in_focus: null})}
|
||||
value={ this.state.mopidy_port } />
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
{this.renderApplyButton()}
|
||||
</form>
|
||||
|
||||
@ -393,7 +393,7 @@ class Settings extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="field">
|
||||
<div className="name">Album library URI</div>
|
||||
<div className="input">
|
||||
<input
|
||||
@ -406,7 +406,7 @@ class Settings extends React.Component {
|
||||
URI used for collecting library albums
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div className="field pusher-connections">
|
||||
<div className="name">Connections</div>
|
||||
|
||||
@ -16,10 +16,6 @@
|
||||
padding: 0 20px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:not(.no-click){
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:before {
|
||||
pointer-events: none;
|
||||
content: '';
|
||||
@ -42,7 +38,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
:root .notouch:not(.dragging) &:not(.no-click) {
|
||||
:root .notouch:not(.dragging) &:not(.list__item--no-interaction){
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: rgba(255,255,255,0.03);
|
||||
@ -57,7 +55,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
:root .light-theme.notouch:not(.dragging) &:not(.no-click) {
|
||||
:root .light-theme.notouch:not(.dragging) &:not(.no-click) &:not(.list__item--no-interaction) {
|
||||
&:hover {
|
||||
background: rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
@ -429,10 +429,6 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.label {
|
||||
.tooltip {
|
||||
left: -4px;
|
||||
|
||||
Reference in New Issue
Block a user