Using snapcast stream params for control_url; SSL explicit for Snapcast connection, fixes #775
This commit is contained in:
@ -1192,11 +1192,7 @@ class IrisCore(pykka.ThreadingActor):
|
||||
##
|
||||
async def update_snapcast_meta(self, *args, **kwargs):
|
||||
track = self.core.playback.get_current_track().get()
|
||||
# Append our server details, so Iris UI can switch to this Mopidy instance
|
||||
# This isn't a great way of doing this, but it works for now.
|
||||
meta = {
|
||||
"control_url": self.config["iris"]["control_url"],
|
||||
}
|
||||
meta = {}
|
||||
|
||||
if track:
|
||||
# Convert the Track to JSON, but to make it a response-ready JSON we need to load it.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
mopidy_iris/static/app.min.js
vendored
6
mopidy_iris/static/app.min.js
vendored
File diff suppressed because one or more lines are too long
@ -115,7 +115,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1634632497";
|
||||
var build = "1634948692";
|
||||
var version = "3.59.1";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -21,30 +21,31 @@ const Header = ({ stream, server }) => {
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
id,
|
||||
meta,
|
||||
meta: {
|
||||
name,
|
||||
artists,
|
||||
images: rawImages,
|
||||
} = {},
|
||||
status,
|
||||
uri: {
|
||||
path,
|
||||
scheme,
|
||||
query: {
|
||||
control_url,
|
||||
} = {},
|
||||
},
|
||||
} = stream || {};
|
||||
let {
|
||||
control_url,
|
||||
images,
|
||||
name,
|
||||
artists,
|
||||
} = meta || {};
|
||||
const controlURL = meta?.control_url ? new URL(meta.control_url) : null;
|
||||
const controlURL = control_url ? new URL(control_url) : null;
|
||||
const controlServer = controlURL ? {
|
||||
url: meta.control_url,
|
||||
url: control_url,
|
||||
ssl: controlURL.protocol === 'https:',
|
||||
host: controlURL.hostname,
|
||||
port: controlURL.port || (controlURL.protocol === 'https:' ? '443' : '80'),
|
||||
} : null;
|
||||
const images = rawImages ? formatImages(digestMopidyImages(controlServer, rawImages)) : null;
|
||||
const current_server_id = useSelector((state) => state.mopidy.current_server);
|
||||
const current_server = useSelector((state) => state.mopidy.servers[current_server_id]);
|
||||
const isCurrentServer = control_url === current_server.url;
|
||||
const isControlSwitchable = controlServer && !isCurrentServer;
|
||||
if (images) images = formatImages(digestMopidyImages(controlServer, images));
|
||||
|
||||
const onClick = () => {
|
||||
if (isControlSwitchable) {
|
||||
@ -71,13 +72,13 @@ const Header = ({ stream, server }) => {
|
||||
{control_url && <div className="tooltip__content">{control_url}</div>}
|
||||
</h5>
|
||||
<ul className="details">
|
||||
<li>{name || path}</li>
|
||||
<li>{name || scheme}</li>
|
||||
{artists && <li><LinksSentence items={artists} type="artist" nolinks /></li>}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const Group = ({
|
||||
group: {
|
||||
@ -160,9 +161,9 @@ const Outputs = () => {
|
||||
groups,
|
||||
};
|
||||
return (
|
||||
<div className="output-control__stream">
|
||||
<div className="output-control__stream" key={`stream_${id}`}>
|
||||
<Header stream={stream} />
|
||||
{groups.map((group) => <Group group={group} /> )}
|
||||
{groups.map((group) => <Group group={group} key={`group_${group.id}`} />)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@ -9,7 +9,6 @@ import { Button } from './Button';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
import { iconFromKeyword } from '../util/helpers';
|
||||
import { I18n } from '../locale';
|
||||
import { decodeUri, encodeUri } from '../util/format';
|
||||
|
||||
const Server = () => {
|
||||
const { id } = useParams();
|
||||
@ -84,6 +83,11 @@ const Server = () => {
|
||||
<I18n path="settings.servers.encryption.description" />
|
||||
</span>
|
||||
</span>
|
||||
{!server.ssl && window.location.protocol === 'https:' && (
|
||||
<span className="red-text">
|
||||
<I18n path="settings.servers.encryption.incompatible" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -19,6 +19,7 @@ const Snapcast = (props) => {
|
||||
snapcast: {
|
||||
host,
|
||||
port,
|
||||
ssl,
|
||||
enabled,
|
||||
streaming_enabled,
|
||||
connected,
|
||||
@ -30,10 +31,11 @@ const Snapcast = (props) => {
|
||||
snapcast_enabled = false,
|
||||
snapcast_host = 'localhost',
|
||||
snapcast_port = '1780',
|
||||
snapcast_ssl = false,
|
||||
} = config || {};
|
||||
|
||||
actions.setEnabled(snapcast_enabled);
|
||||
actions.setConnection({ host: snapcast_host, port: snapcast_port });
|
||||
actions.setConnection({ host: snapcast_host, port: snapcast_port, ssl: snapcast_ssl });
|
||||
}
|
||||
|
||||
return (
|
||||
@ -111,6 +113,34 @@ const Snapcast = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field checkbox">
|
||||
<div className="name">
|
||||
<I18n path="snapcast.encryption.label" />
|
||||
</div>
|
||||
<div className="input">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="ssl"
|
||||
value={ssl}
|
||||
checked={ssl}
|
||||
onChange={() => actions.setConnection({ ssl: !ssl })}
|
||||
/>
|
||||
<span className="label tooltip">
|
||||
<I18n path="snapcast.encryption.sublabel" />
|
||||
<span className="tooltip__content">
|
||||
<I18n path="snapcast.encryption.description" />
|
||||
</span>
|
||||
</span>
|
||||
{!ssl && window.location.protocol === 'https:' && (
|
||||
<span className="red-text">
|
||||
<I18n path="snapcast.encryption.incompatible" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{connected && enabled && <SnapcastGroups match={match} history={history} />}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -217,6 +217,11 @@ snapcast:
|
||||
latency: Latency
|
||||
stream: Stream
|
||||
volume: Volume
|
||||
encryption:
|
||||
label: Encryption
|
||||
sublabel: Use SSL
|
||||
description: Requires a SSL proxy
|
||||
incompatible: ' (required when connecting from a HTTPS browser session)'
|
||||
authentication:
|
||||
popup_blocked: Popup blocked. Please allow popups and try again.
|
||||
failed: Authorization failed. %{origin} is not the configured authorization_url.
|
||||
@ -438,6 +443,7 @@ settings:
|
||||
label: Encryption
|
||||
sublabel: Use SSL
|
||||
description: Requires a SSL proxy
|
||||
incompatible: ' (required when connecting from a HTTPS browser session)'
|
||||
switch: Switch to this server
|
||||
reconnect: Reconnect
|
||||
services:
|
||||
|
||||
@ -167,9 +167,9 @@ const SnapcastMiddleware = (function () {
|
||||
clearTimeout(reconnectTimer);
|
||||
|
||||
store.dispatch({ type: 'SNAPCAST_CONNECTING' });
|
||||
|
||||
const { host, port, ssl } = store.getState().snapcast;
|
||||
socket = new WebSocket(
|
||||
`ws${window.location.protocol === 'https:' ? 's' : ''}://${store.getState().snapcast.host}:${store.getState().snapcast.port}/jsonrpc`,
|
||||
`ws${ssl ? 's' : ''}://${host}:${port}/jsonrpc`,
|
||||
);
|
||||
|
||||
socket.onopen = () => {
|
||||
|
||||
@ -106,6 +106,7 @@ let initialState = {
|
||||
connected: false,
|
||||
host: 'localhost',
|
||||
port: '1780',
|
||||
ssl: false,
|
||||
streams: {},
|
||||
groups: {},
|
||||
clients: {},
|
||||
|
||||
Reference in New Issue
Block a user