2019-11-05 16:05:49 +13:00
|
|
|
|
|
|
|
|
import React from 'react';
|
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
|
import { bindActionCreators } from 'redux';
|
2020-03-03 16:39:37 +13:00
|
|
|
import { collate } from '../util/format';
|
|
|
|
|
import { sortItems } from '../util/arrays';
|
2020-04-28 21:24:17 +12:00
|
|
|
import { iconFromKeyword } from '../util/helpers';
|
2019-11-05 16:05:49 +13:00
|
|
|
import VolumeControl from './Fields/VolumeControl';
|
|
|
|
|
import MuteControl from './Fields/MuteControl';
|
|
|
|
|
import TextField from './Fields/TextField';
|
|
|
|
|
import SnapcastClients from './SnapcastClients';
|
|
|
|
|
import Icon from './Icon';
|
|
|
|
|
import Link from './Link';
|
|
|
|
|
import * as actions from '../services/snapcast/actions';
|
2019-11-07 17:01:27 +13:00
|
|
|
import SelectField from './Fields/SelectField';
|
2019-11-05 16:05:49 +13:00
|
|
|
|
|
|
|
|
const SnapcastGroups = (props) => {
|
|
|
|
|
const {
|
|
|
|
|
actions,
|
|
|
|
|
show_disconnected_clients,
|
|
|
|
|
streams,
|
|
|
|
|
groups,
|
|
|
|
|
clients,
|
|
|
|
|
history,
|
|
|
|
|
match: { params: { id: groupId } },
|
|
|
|
|
} = props;
|
|
|
|
|
|
|
|
|
|
const streamsArray = Object.keys(streams).map((id) => streams[id]);
|
|
|
|
|
const groupsArray = Object.keys(groups).map((id) => groups[id]);
|
|
|
|
|
|
|
|
|
|
if (!groups || groupsArray.length <= 0) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-08 09:15:45 +12:00
|
|
|
const group = groupId && groups[groupId]
|
|
|
|
|
? collate(groups[groupId], { clients })
|
|
|
|
|
: null;
|
2019-11-05 16:05:49 +13:00
|
|
|
|
2020-04-08 09:15:45 +12:00
|
|
|
const renderGroup = () => {
|
|
|
|
|
if (!group) return null;
|
2019-11-05 16:05:49 +13:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="snapcast__group" key={group.id}>
|
|
|
|
|
<div className="field text">
|
|
|
|
|
<div className="name">
|
|
|
|
|
Name
|
|
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
|
|
|
|
<TextField
|
|
|
|
|
value={group.name}
|
|
|
|
|
onChange={value => actions.setGroupName(group.id, value)}
|
2020-05-03 13:54:34 +12:00
|
|
|
autosave
|
2019-11-05 16:05:49 +13:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="field dropdown">
|
|
|
|
|
<div className="name">
|
|
|
|
|
Stream
|
|
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
2019-11-07 17:01:27 +13:00
|
|
|
<SelectField
|
|
|
|
|
onChange={(value) => actions.setGroupStream(group.id, value)}
|
|
|
|
|
value={group.stream_id}
|
|
|
|
|
options={streamsArray.map((stream) => (
|
2019-11-08 16:39:25 +13:00
|
|
|
{
|
|
|
|
|
key: `group_${group.id}_stream_${stream.id}`,
|
|
|
|
|
value: stream.id,
|
|
|
|
|
label: `${stream.id} (${stream.status})`,
|
|
|
|
|
}
|
2019-11-07 17:01:27 +13:00
|
|
|
))}
|
2020-05-03 13:54:34 +12:00
|
|
|
autosave
|
2019-11-07 17:01:27 +13:00
|
|
|
/>
|
2019-11-05 16:05:49 +13:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="field">
|
|
|
|
|
<div className="name">
|
|
|
|
|
Volume
|
|
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
|
|
|
|
<MuteControl
|
2019-11-06 17:01:24 +13:00
|
|
|
className="snapcast__group__mute-control snapcast__mute-control"
|
2019-11-07 17:01:27 +13:00
|
|
|
mute={group.mute}
|
2019-11-05 16:05:49 +13:00
|
|
|
onMuteChange={(mute) => actions.setGroupMute(group.id, mute)}
|
|
|
|
|
/>
|
|
|
|
|
<VolumeControl
|
2019-11-06 17:01:24 +13:00
|
|
|
className="snapcast__group__volume-control snapcast__volume-control"
|
2019-11-08 16:39:25 +13:00
|
|
|
volume={group.volume}
|
2019-11-07 17:01:27 +13:00
|
|
|
mute={group.mute}
|
2019-11-05 16:05:49 +13:00
|
|
|
onVolumeChange={(percent, previousPercent) => actions.setGroupVolume(group.id, percent, previousPercent)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2019-11-10 16:23:56 +13:00
|
|
|
<SnapcastClients
|
|
|
|
|
group={group}
|
|
|
|
|
groups={groupsArray}
|
|
|
|
|
actions={actions}
|
|
|
|
|
show_disconnected_clients={show_disconnected_clients}
|
|
|
|
|
/>
|
2019-11-05 16:05:49 +13:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-08 09:15:45 +12:00
|
|
|
const renderMenuItem = (simpleGroup) => {
|
|
|
|
|
const group = collate(simpleGroup, { clients });
|
|
|
|
|
const anyClients = (
|
|
|
|
|
!show_disconnected_clients && (
|
|
|
|
|
!group.clients ||
|
|
|
|
|
!group.clients.length ||
|
|
|
|
|
!group.clients.filter((client) => client.connected).length
|
|
|
|
|
)
|
|
|
|
|
);
|
2019-11-05 16:05:49 +13:00
|
|
|
return (
|
|
|
|
|
<Link
|
2020-04-08 09:15:45 +12:00
|
|
|
className={`snapcast__groups__menu-item menu-item${anyClients ? ' menu-item--no-clients' : ''}`}
|
2019-11-05 16:05:49 +13:00
|
|
|
activeClassName="menu-item--active"
|
|
|
|
|
key={group.id}
|
|
|
|
|
history={history}
|
2020-04-26 22:04:39 +12:00
|
|
|
to={`/settings/services/snapcast/${group.id}`}
|
2019-11-05 16:05:49 +13:00
|
|
|
scrollTo="#services-snapcast-groups"
|
|
|
|
|
>
|
|
|
|
|
<div className="snapcast__groups__menu-item__inner menu-item__inner">
|
2020-04-28 21:24:17 +12:00
|
|
|
<Icon className="menu-item__icon" name={iconFromKeyword(group.name.toLowerCase()) || 'speaker_group'} />
|
2019-11-05 16:05:49 +13:00
|
|
|
<div className="menu-item__title">
|
|
|
|
|
{group.name}
|
2019-11-11 21:10:17 +13:00
|
|
|
{group.mute && (
|
|
|
|
|
<Icon name="volume_off" />
|
|
|
|
|
)}
|
2019-11-05 16:05:49 +13:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Link>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2020-04-26 22:04:39 +12:00
|
|
|
<div className="sub-tabs snapcast__groups" id="services-snapcast-groups">
|
|
|
|
|
<div className="sub-tabs__menu snapcast__groups__menu menu">
|
2019-11-05 16:05:49 +13:00
|
|
|
<div className="menu__inner">
|
2020-03-03 16:39:37 +13:00
|
|
|
{sortItems(groupsArray, 'name').map((group) => renderMenuItem(group))}
|
2019-11-05 16:05:49 +13:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{renderGroup()}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
actions: bindActionCreators(actions, dispatch),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(SnapcastGroups);
|