Client commands stored in localStorage
This commit is contained in:
@ -192,6 +192,14 @@ class IrisCore(object):
|
||||
callback = kwargs.get('callback', None)
|
||||
data = kwargs.get('data', {})
|
||||
|
||||
if (not self.config['iris']['broadlink_enabled']):
|
||||
error = {'message': 'Broadlink API not enabled'}
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
else:
|
||||
return error
|
||||
|
||||
|
||||
# Use client_id and client_secret from config
|
||||
# This was introduced in Mopidy-Spotify 3.1.0
|
||||
url = 'http://'+self.config['iris']['broadlink_host']+':'+str(self.config['iris']['broadlink_port'])+"/"
|
||||
|
||||
@ -3009,6 +3009,33 @@ select {
|
||||
select:focus, .light-theme
|
||||
select:active {
|
||||
background: #eeeae7; }
|
||||
textarea::placeholder,
|
||||
input[type="text"]::placeholder,
|
||||
input[type="email"]::placeholder,
|
||||
input[type="number"]::placeholder,
|
||||
input[type="email"]::placeholder,
|
||||
input[type="date"]::placeholder,
|
||||
input[type="file"]::placeholder,
|
||||
select::placeholder {
|
||||
color: rgba(128, 128, 128, 0.6); }
|
||||
textarea:-ms-input-placeholder,
|
||||
input[type="text"]:-ms-input-placeholder,
|
||||
input[type="email"]:-ms-input-placeholder,
|
||||
input[type="number"]:-ms-input-placeholder,
|
||||
input[type="email"]:-ms-input-placeholder,
|
||||
input[type="date"]:-ms-input-placeholder,
|
||||
input[type="file"]:-ms-input-placeholder,
|
||||
select:-ms-input-placeholder {
|
||||
color: rgba(128, 128, 128, 0.6); }
|
||||
textarea::-ms-input-placeholder,
|
||||
input[type="text"]::-ms-input-placeholder,
|
||||
input[type="email"]::-ms-input-placeholder,
|
||||
input[type="number"]::-ms-input-placeholder,
|
||||
input[type="email"]::-ms-input-placeholder,
|
||||
input[type="date"]::-ms-input-placeholder,
|
||||
input[type="file"]::-ms-input-placeholder,
|
||||
select::-ms-input-placeholder {
|
||||
color: rgba(128, 128, 128, 0.6); }
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield; }
|
||||
|
||||
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
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1538074514";
|
||||
var build = "1538100775";
|
||||
var version = "3.26.2";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -65,15 +65,22 @@ class OutputControl extends React.Component{
|
||||
<div>
|
||||
{
|
||||
clients.map(client => {
|
||||
|
||||
var commands = {};
|
||||
if (this.props.snapcast_client_commands[client.id]){
|
||||
commands = this.props.snapcast_client_commands[client.id];
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="output-control__item outputs__item--snapcast" key={client.id}>
|
||||
<div className="output-control__item__name">
|
||||
{client.name}
|
||||
</div>
|
||||
<div className="output-control__item__details">
|
||||
{client.commands && client.commands.power_on ? <SnapcastPowerButton
|
||||
{commands && commands.power_on ? <SnapcastPowerButton
|
||||
className="output-control__item__power output-control__item__power--on"
|
||||
client={client}
|
||||
onClick={e => this.props.snapcastActions.sendClientCommand(client.id, commands.power_on)}
|
||||
/> : null}
|
||||
<VolumeControl
|
||||
className="output-control__item__volume"
|
||||
@ -165,9 +172,10 @@ const mapStateToProps = (state, ownProps) => {
|
||||
http_streaming_enabled: state.core.http_streaming_enabled,
|
||||
http_streaming_volume: state.core.http_streaming_volume,
|
||||
http_streaming_mute: state.core.http_streaming_mute,
|
||||
snapcast_enabled: (state.pusher.config ? state.pusher.config.snapcast_enabled : null),
|
||||
pusher_connected: state.pusher.connected,
|
||||
snapcast_clients: state.snapcast.clients
|
||||
snapcast_enabled: (state.pusher.config ? state.pusher.config.snapcast_enabled : null),
|
||||
snapcast_clients: state.snapcast.clients,
|
||||
snapcast_client_commands: (state.snapcast.client_commands ? state.snapcast.client_commands : {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import Icon from '../Icon'
|
||||
import * as helpers from '../../helpers';
|
||||
import * as snapcastActions from '../../services/snapcast/actions';
|
||||
|
||||
class SnapcastPowerButton extends React.Component{
|
||||
export default class SnapcastPowerButton extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
@ -17,9 +17,7 @@ class SnapcastPowerButton extends React.Component{
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
|
||||
// Dynamic-ify the command itself
|
||||
this.props.snapcastActions.sendClientCommand(this.props.client.id, 'power_on');
|
||||
this.props.onClick(e);
|
||||
}
|
||||
|
||||
render(){
|
||||
@ -33,16 +31,4 @@ class SnapcastPowerButton extends React.Component{
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
snapcastActions: bindActionCreators(snapcastActions, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SnapcastPowerButton)
|
||||
}
|
||||
@ -42,6 +42,7 @@ export default class TextField extends React.Component{
|
||||
onFocus={e => this.handleFocus(e)}
|
||||
onBlur={e => this.handleBlur(e)}
|
||||
value={this.state.value}
|
||||
placeholder={this.props.placeholder ? this.props.placeholder : null}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -87,6 +87,12 @@ class Snapcast extends React.Component{
|
||||
}
|
||||
|
||||
if (this.state.clients_expanded.includes(client.id)){
|
||||
|
||||
var commands = {};
|
||||
if (this.props.client_commands[client.id]){
|
||||
commands = this.props.client_commands[client.id];
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={class_name+" snapcast__client--expanded"} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={e => this.toggleClientExpanded(client.id)}>
|
||||
@ -170,9 +176,9 @@ class Snapcast extends React.Component{
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={value => this.props.snapcastActions.setClientCommand(client.id, "power_on", value)}
|
||||
value={client.commands && client.commands.power_on ? client.commands.power_on : ""}
|
||||
placeholder="Leave empty to disable"
|
||||
onChange={value => this.props.snapcastActions.setClientCommand(client.id, {power_on: value})}
|
||||
value={commands.power_on ? commands.power_on : ""}
|
||||
placeholder="sendCommand/power_on"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -185,9 +191,9 @@ class Snapcast extends React.Component{
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={value => this.props.snapcastActions.setClientCommand(client.id, "power_off", value)}
|
||||
value={client.commands && client.commands.power_off ? client.commands.power_off : ""}
|
||||
placeholder="Leave empty to disable"
|
||||
onChange={value => this.props.snapcastActions.setClientCommand(client.id, {power_off: value})}
|
||||
value={commands.power_off ? commands.power_off : ""}
|
||||
placeholder="sendCommand/power_off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -344,7 +350,8 @@ const mapStateToProps = (state, ownProps) => {
|
||||
show_disconnected_clients: (state.ui.snapcast_show_disconnected_clients !== undefined ? state.ui.snapcast_show_disconnected_clients : false),
|
||||
streams: (state.snapcast.streams ? state.snapcast.streams : null),
|
||||
groups: (state.snapcast.groups ? state.snapcast.groups : null),
|
||||
clients: (state.snapcast.clients ? state.snapcast.clients : null)
|
||||
clients: (state.snapcast.clients ? state.snapcast.clients : null),
|
||||
client_commands: (state.snapcast.client_commands ? state.snapcast.client_commands : {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -204,6 +204,15 @@ const localstorageMiddleware = (function(){
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_CLIENT_COMMANDS_UPDATED':
|
||||
helpers.setStorage(
|
||||
'snapcast',
|
||||
{
|
||||
client_commands: action.client_commands
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SUPPRESS_BROADCAST':
|
||||
var ui = helpers.getStorage('ui');
|
||||
if (ui.suppressed_broadcasts !== undefined){
|
||||
|
||||
@ -37,15 +37,29 @@ export function setClientLatency(id, latency){
|
||||
}
|
||||
}
|
||||
|
||||
export function setClientCommand(id, name, command){
|
||||
export function setClientCommand(id, command){
|
||||
return {
|
||||
type: 'SNAPCAST_SET_CLIENT_COMMAND',
|
||||
id: id,
|
||||
name: name,
|
||||
command: command
|
||||
}
|
||||
}
|
||||
|
||||
export function sendClientCommand(id, command){
|
||||
return {
|
||||
type: 'SNAPCAST_SEND_CLIENT_COMMAND',
|
||||
id: id,
|
||||
command: command
|
||||
}
|
||||
}
|
||||
|
||||
export function clientCommandsUpdated(client_commands){
|
||||
return {
|
||||
type: 'SNAPCAST_CLIENT_COMMANDS_UPDATED',
|
||||
client_commands: client_commands
|
||||
}
|
||||
}
|
||||
|
||||
export function setClientGroup(id, group_id){
|
||||
return {
|
||||
type: 'SNAPCAST_SET_CLIENT_GROUP',
|
||||
|
||||
@ -231,12 +231,37 @@ const SnapcastMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_COMMAND':
|
||||
var client = snapcast.clients[action.id];
|
||||
if (!client.commands){
|
||||
client.commands = {};
|
||||
}
|
||||
client.commands[action.name] = action.command;
|
||||
store.dispatch(snapcastActions.clientLoaded(client));
|
||||
var client_commands_index = Object.assign({}, snapcast.client_commands);
|
||||
|
||||
if (client_commands_index[action.id]){
|
||||
var client_command = Object.assign({}, client_commands_index[action.id], action.command);
|
||||
} else {
|
||||
var client_command = action.command;
|
||||
}
|
||||
client_commands_index[action.id] = client_command;
|
||||
|
||||
store.dispatch(snapcastActions.clientCommandsUpdated(client_commands_index));
|
||||
break
|
||||
|
||||
case 'SNAPCAST_SEND_CLIENT_COMMAND':
|
||||
store.dispatch(
|
||||
pusherActions.request(
|
||||
'send_broadlink_command',
|
||||
{
|
||||
command: action.command
|
||||
},
|
||||
response => {
|
||||
console.log(response);
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not send command',
|
||||
error,
|
||||
error.message
|
||||
));
|
||||
}
|
||||
)
|
||||
);
|
||||
break
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_GROUP':
|
||||
|
||||
@ -6,6 +6,19 @@ export default function reducer(snapcast = {}, action){
|
||||
var server = Object.assign({}, action.server);
|
||||
return Object.assign({}, snapcast, { server: server });
|
||||
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_COMMAND':
|
||||
var client_commands = snapcast.client_commands[action.id];
|
||||
if (!client_commands){
|
||||
client.commands = {};
|
||||
}
|
||||
client_commands[action.name] = action.command;
|
||||
action.client_commands = client_commands;
|
||||
break
|
||||
|
||||
case 'SNAPCAST_CLIENT_COMMANDS_UPDATED':
|
||||
return Object.assign({}, snapcast, { client_commands: action.client_commands });
|
||||
|
||||
case 'SNAPCAST_CLIENTS_LOADED':
|
||||
var clients = Object.assign({}, snapcast.clients);
|
||||
for (var client of action.clients){
|
||||
|
||||
@ -48,6 +48,18 @@ select {
|
||||
background: darken($faint_grey, 3%);
|
||||
}
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: rgba(128, 128, 128, 0.6);
|
||||
}
|
||||
|
||||
&:-ms-input-placeholder {
|
||||
color: rgba(128, 128, 128, 0.6);
|
||||
}
|
||||
|
||||
&::-ms-input-placeholder {
|
||||
color: rgba(128, 128, 128, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="number"]{
|
||||
|
||||
Reference in New Issue
Block a user