Adding advanced server controls
This commit is contained in:
@ -4291,118 +4291,102 @@ input[type="submit"] {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0; } }
|
right: 0; } }
|
||||||
|
|
||||||
.snapcast .group.list {
|
.snapcast .group:not(:first-child) {
|
||||||
|
padding-top: 20px; }
|
||||||
|
|
||||||
|
.snapcast .group .clients {
|
||||||
padding: 0 10px; }
|
padding: 0 10px; }
|
||||||
.snapcast .group.list:not(:first-child) {
|
.snapcast .group .clients .client {
|
||||||
padding-top: 15px; }
|
border: 0;
|
||||||
.snapcast .group.list .list-item {
|
padding: 0;
|
||||||
padding: 20px 0 0 0; }
|
clear: both; }
|
||||||
.snapcast .group.list .list-item:not(.header) {
|
.snapcast .group .clients .client::after {
|
||||||
border: 0; }
|
content: '';
|
||||||
.snapcast .group.list .list-item > .name {
|
clear: both;
|
||||||
|
display: block; }
|
||||||
|
.snapcast .group .clients .client:not(:first-child) {
|
||||||
|
padding-top: 8px; }
|
||||||
|
.snapcast .group .clients .client > .name {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
position: relative; }
|
position: relative;
|
||||||
.snapcast .group.list .list-item > .name .status {
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 0; }
|
||||||
|
.snapcast .group .clients .client > .name input {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 30px; }
|
||||||
|
.snapcast .group .clients .client > .name .tools {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: -2px;
|
||||||
left: 0;
|
right: 0;
|
||||||
z-index: 2;
|
z-index: 2; }
|
||||||
padding: 12px;
|
.snapcast .group .clients .client > .name .tools .disconnected {
|
||||||
cursor: default; }
|
padding: 12px 0;
|
||||||
.snapcast .group.list .list-item > .name .status .fa {
|
cursor: default;
|
||||||
font-size: 12px; }
|
font-size: 12px; }
|
||||||
.snapcast .group.list .list-item > .name input {
|
.snapcast .group .clients .client > .volume {
|
||||||
padding-left: 30px; }
|
|
||||||
.snapcast .group.list .list-item > .volume {
|
|
||||||
width: 28%;
|
width: 28%;
|
||||||
padding-left: 2%; }
|
padding-left: 2%; }
|
||||||
.snapcast .group.list .list-item > .latency {
|
.snapcast .group .clients .client > .latency {
|
||||||
width: 28%;
|
width: 28%;
|
||||||
padding-left: 2%; }
|
padding-left: 2%; }
|
||||||
.snapcast .group.list .list-item.header {
|
.snapcast .group .clients .client > .volume input,
|
||||||
padding-top: 0;
|
.snapcast .group .clients .client > .latency input {
|
||||||
vertical-align: bottom;
|
width: 20%; }
|
||||||
cursor: default; }
|
.snapcast .group .clients .client .volume-control {
|
||||||
.snapcast .group.list .list-item.header .name {
|
display: inline-block;
|
||||||
font-size: 14px;
|
vertical-align: middle;
|
||||||
color: #FFFFFF;
|
padding-top: 4px;
|
||||||
text-transform: none;
|
width: 80%;
|
||||||
font-weight: 600;
|
padding-right: 10px;
|
||||||
line-height: 14px; }
|
box-sizing: border-box; }
|
||||||
.snapcast .group.list .list-item.client {
|
.snapcast .group .clients .client .volume-control .mute-control {
|
||||||
padding: 20px 0 0 0; }
|
display: inline-block;
|
||||||
.snapcast .group.list .list-item.client::after {
|
float: left;
|
||||||
content: '';
|
padding: 0 10px;
|
||||||
clear: both;
|
|
||||||
display: block; }
|
|
||||||
.snapcast .group.list .list-item.client > .name {
|
|
||||||
display: block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 0; }
|
border: 0; }
|
||||||
.snapcast .group.list .list-item.client > .name input {
|
.snapcast .group .clients .client .volume-control .slider-wrapper {
|
||||||
width: 100%; }
|
margin-left: 25px; }
|
||||||
.snapcast .group.list .list-item.client > .volume input,
|
.snapcast .group .clients .client .volume-control.muted .slider .progress {
|
||||||
.snapcast .group.list .list-item.client > .latency input {
|
background: #a3a19f; }
|
||||||
width: 20%; }
|
.snapcast .group .clients .client .latency-control {
|
||||||
.snapcast .group.list .list-item.client .volume-control {
|
display: inline-block;
|
||||||
display: inline-block;
|
vertical-align: middle;
|
||||||
vertical-align: middle;
|
padding-top: 4px;
|
||||||
padding-top: 4px;
|
width: 80%;
|
||||||
width: 80%;
|
padding-right: 10px;
|
||||||
padding-right: 10px;
|
box-sizing: border-box; }
|
||||||
box-sizing: border-box; }
|
.snapcast .group .clients .client .latency-control .zero {
|
||||||
.snapcast .group.list .list-item.client .volume-control .mute-control {
|
position: absolute;
|
||||||
display: inline-block;
|
top: -4px;
|
||||||
float: left;
|
left: 50%;
|
||||||
padding: 0 10px;
|
bottom: 0;
|
||||||
border: 0; }
|
width: 1px;
|
||||||
.snapcast .group.list .list-item.client .volume-control .slider-wrapper {
|
background: #383734;
|
||||||
margin-left: 40px; }
|
z-index: 1; }
|
||||||
.snapcast .group.list .list-item.client .volume-control.muted .slider .progress {
|
.snapcast .group .clients .client .latency-control .progress.positive {
|
||||||
background: #a3a19f; }
|
border-top-left-radius: 0;
|
||||||
.snapcast .group.list .list-item.client .latency-control {
|
border-bottom-left-radius: 0; }
|
||||||
display: inline-block;
|
.snapcast .group .clients .client .latency-control .progress.negative {
|
||||||
vertical-align: middle;
|
border-top-right-radius: 0;
|
||||||
padding-top: 4px;
|
border-bottom-right-radius: 0; }
|
||||||
width: 80%;
|
|
||||||
padding-right: 10px;
|
|
||||||
box-sizing: border-box; }
|
|
||||||
.snapcast .group.list .list-item.client .latency-control .zero {
|
|
||||||
position: absolute;
|
|
||||||
top: -4px;
|
|
||||||
left: 50%;
|
|
||||||
bottom: 0;
|
|
||||||
width: 1px;
|
|
||||||
background: #383734;
|
|
||||||
z-index: 1; }
|
|
||||||
.snapcast .group.list .list-item.client .latency-control .progress.positive {
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-bottom-left-radius: 0; }
|
|
||||||
.snapcast .group.list .list-item.client .latency-control .progress.negative {
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0; }
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.snapcast .group.list .list-item {
|
.snapcast .group .clients .client {
|
||||||
padding-left: 0 !important;
|
padding-left: 0 !important;
|
||||||
padding-right: 0 !important; }
|
padding-right: 0 !important; }
|
||||||
.snapcast .group.list .list-item.header {
|
.snapcast .group .clients .client .col {
|
||||||
display: block; }
|
|
||||||
.snapcast .group.list .list-item.header .volume,
|
|
||||||
.snapcast .group.list .list-item.header .latency {
|
|
||||||
display: none !important; }
|
|
||||||
.snapcast .group.list .list-item .col {
|
|
||||||
float: none !important;
|
float: none !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0; }
|
padding-right: 0; }
|
||||||
.snapcast .group.list .list-item .col::after {
|
.snapcast .group .clients .client .col::after {
|
||||||
content: '';
|
content: '';
|
||||||
clear: both;
|
clear: both;
|
||||||
display: block; }
|
display: block; }
|
||||||
.snapcast .group.list .list-item .col:not(.header) {
|
.snapcast .group .clients .client .col:not(.header) {
|
||||||
line-height: 45px; }
|
line-height: 45px; }
|
||||||
.snapcast .group.list .list-item .col.volume {
|
.snapcast .group .clients .client .col.volume {
|
||||||
padding-bottom: 20px !important; } }
|
padding-bottom: 20px !important; } }
|
||||||
|
|
||||||
aside {
|
aside {
|
||||||
@ -4549,7 +4533,6 @@ aside {
|
|||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 -10px -1px -10px;
|
margin: 0 -10px -1px -10px;
|
||||||
padding: 14px 30px 13px 10px;
|
padding: 14px 30px 13px 10px;
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.05); }
|
border-top: 1px solid rgba(255, 255, 255, 0.05); }
|
||||||
@ -4604,91 +4587,95 @@ aside {
|
|||||||
.list .list-item .uri-placeholder {
|
.list .list-item .uri-placeholder {
|
||||||
word-break: break-all; }
|
word-break: break-all; }
|
||||||
|
|
||||||
.list.track-list .list-item .col.name {
|
.list.track-list .list-item {
|
||||||
width: 40%; }
|
cursor: pointer; }
|
||||||
|
.list.track-list .list-item .col.name {
|
||||||
.list.track-list .list-item .col.artists, .list.track-list .list-item .col.album {
|
width: 40%; }
|
||||||
width: 25%; }
|
.list.track-list .list-item .col.artists, .list.track-list .list-item .col.album {
|
||||||
|
|
||||||
.list.track-list .list-item .col.duration {
|
|
||||||
width: 5%; }
|
|
||||||
|
|
||||||
:root .dragging .list.track-list .list-item.hover, .list.track-list .list-item.touch-drag-hover {
|
|
||||||
border-top: 3px solid #32b5f2;
|
|
||||||
margin-top: -3px;
|
|
||||||
background: transparent; }
|
|
||||||
|
|
||||||
.list.track-list .list-item.has-touch-drag-zone {
|
|
||||||
padding-left: 45px; }
|
|
||||||
.list.track-list .list-item.has-touch-drag-zone .drag-zone {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 34px;
|
|
||||||
font-size: 14px;
|
|
||||||
display: block;
|
|
||||||
color: #a3a19f; }
|
|
||||||
.list.track-list .list-item.has-touch-drag-zone .drag-zone .fa {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 10px;
|
|
||||||
margin-top: -6px;
|
|
||||||
pointer-events: none; }
|
|
||||||
|
|
||||||
.list.playlist-list .list-item .col.name {
|
|
||||||
width: 50%; }
|
|
||||||
|
|
||||||
.list.playlist-list .list-item .col.owner {
|
|
||||||
width: 20%; }
|
|
||||||
|
|
||||||
.list.playlist-list .list-item .col.source, .list.playlist-list .list-item .col.can_edit, .list.playlist-list .list-item .col.tracks_total, .list.playlist-list .list-item .col.popularity {
|
|
||||||
width: 10%; }
|
|
||||||
|
|
||||||
.list.album-list .list-item .col.name, .list.album-list .list-item .col.artists {
|
|
||||||
width: 30%; }
|
|
||||||
|
|
||||||
.list.album-list .list-item .col.added_at, .list.album-list .list-item .col.release_date {
|
|
||||||
width: 15%; }
|
|
||||||
|
|
||||||
.list.album-list .list-item .col.tracks_total {
|
|
||||||
width: 10%; }
|
|
||||||
|
|
||||||
.list.library-local-album-list .list-item .col.name, .list.library-local-album-list .list-item .col.artists {
|
|
||||||
width: 45%; }
|
|
||||||
|
|
||||||
.list.library-local-album-list .list-item .col.tracks_total {
|
|
||||||
width: 10%; }
|
|
||||||
|
|
||||||
.list.artist-list .list-item .col.name {
|
|
||||||
width: 70%; }
|
|
||||||
|
|
||||||
.list.artist-list .list-item .col.followers_total, .list.artist-list .list-item .col.popularity {
|
|
||||||
width: 15%; }
|
|
||||||
|
|
||||||
.list.queue-track-list .list-item {
|
|
||||||
padding-right: 60px; }
|
|
||||||
.list.queue-track-list .list-item .col.name, .list.queue-track-list .list-item .col.artists, .list.queue-track-list .list-item .col.album {
|
|
||||||
width: 25%; }
|
width: 25%; }
|
||||||
.list.queue-track-list .list-item .col.added {
|
.list.track-list .list-item .col.duration {
|
||||||
|
width: 5%; }
|
||||||
|
:root .dragging .list.track-list .list-item.hover, .list.track-list .list-item.touch-drag-hover {
|
||||||
|
border-top: 3px solid #32b5f2;
|
||||||
|
margin-top: -3px;
|
||||||
|
background: transparent; }
|
||||||
|
.list.track-list .list-item.has-touch-drag-zone {
|
||||||
|
padding-left: 45px; }
|
||||||
|
.list.track-list .list-item.has-touch-drag-zone .drag-zone {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 34px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
color: #a3a19f; }
|
||||||
|
.list.track-list .list-item.has-touch-drag-zone .drag-zone .fa {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 10px;
|
||||||
|
margin-top: -6px;
|
||||||
|
pointer-events: none; }
|
||||||
|
|
||||||
|
.list.playlist-list .list-item {
|
||||||
|
cursor: pointer; }
|
||||||
|
.list.playlist-list .list-item .col.name {
|
||||||
|
width: 50%; }
|
||||||
|
.list.playlist-list .list-item .col.owner {
|
||||||
width: 20%; }
|
width: 20%; }
|
||||||
.list.queue-track-list .list-item .col.added .by {
|
.list.playlist-list .list-item .col.source, .list.playlist-list .list-item .col.can_edit, .list.playlist-list .list-item .col.tracks_total, .list.playlist-list .list-item .col.popularity {
|
||||||
padding-right: 0.25em; }
|
width: 10%; }
|
||||||
.list.queue-track-list .list-item .col.added .from:before {
|
|
||||||
content: '(';
|
|
||||||
display: inline-block; }
|
|
||||||
.list.queue-track-list .list-item .col.added .from:after {
|
|
||||||
content: ')';
|
|
||||||
display: inline-block; }
|
|
||||||
|
|
||||||
.list.queue-history-track-list .list-item .col.name {
|
.list.album-list .list-item {
|
||||||
width: 60%; }
|
cursor: pointer; }
|
||||||
|
.list.album-list .list-item .col.name, .list.album-list .list-item .col.artists {
|
||||||
|
width: 30%; }
|
||||||
|
.list.album-list .list-item .col.added_at, .list.album-list .list-item .col.release_date {
|
||||||
|
width: 15%; }
|
||||||
|
.list.album-list .list-item .col.tracks_total {
|
||||||
|
width: 10%; }
|
||||||
|
|
||||||
.list.queue-history-track-list .list-item .col.played_at, .list.queue-history-track-list .list-item .col.source {
|
.list.library-local-album-list .list-item {
|
||||||
width: 20%; }
|
cursor: pointer; }
|
||||||
|
.list.library-local-album-list .list-item .col.name, .list.library-local-album-list .list-item .col.artists {
|
||||||
|
width: 45%; }
|
||||||
|
.list.library-local-album-list .list-item .col.tracks_total {
|
||||||
|
width: 10%; }
|
||||||
|
|
||||||
|
.list.artist-list .list-item {
|
||||||
|
cursor: pointer; }
|
||||||
|
.list.artist-list .list-item .col.name {
|
||||||
|
width: 70%; }
|
||||||
|
.list.artist-list .list-item .col.followers_total, .list.artist-list .list-item .col.popularity {
|
||||||
|
width: 15%; }
|
||||||
|
|
||||||
|
.list.queue-track-list {
|
||||||
|
cursor: pointer; }
|
||||||
|
.list.queue-track-list .list-item {
|
||||||
|
padding-right: 60px; }
|
||||||
|
.list.queue-track-list .list-item .col.name, .list.queue-track-list .list-item .col.artists, .list.queue-track-list .list-item .col.album {
|
||||||
|
width: 25%; }
|
||||||
|
.list.queue-track-list .list-item .col.added {
|
||||||
|
width: 20%; }
|
||||||
|
.list.queue-track-list .list-item .col.added .by {
|
||||||
|
padding-right: 0.25em; }
|
||||||
|
.list.queue-track-list .list-item .col.added .from:before {
|
||||||
|
content: '(';
|
||||||
|
display: inline-block; }
|
||||||
|
.list.queue-track-list .list-item .col.added .from:after {
|
||||||
|
content: ')';
|
||||||
|
display: inline-block; }
|
||||||
|
|
||||||
|
.list.queue-history-track-list .list-item {
|
||||||
|
cursor: pointer; }
|
||||||
|
.list.queue-history-track-list .list-item .col.name {
|
||||||
|
width: 60%; }
|
||||||
|
.list.queue-history-track-list .list-item .col.played_at, .list.queue-history-track-list .list-item .col.source {
|
||||||
|
width: 20%; }
|
||||||
|
|
||||||
.list.related-artist-list {
|
.list.related-artist-list {
|
||||||
padding-bottom: 20px; }
|
padding-bottom: 20px;
|
||||||
|
cursor: pointer; }
|
||||||
.list.related-artist-list .artist {
|
.list.related-artist-list .artist {
|
||||||
display: block;
|
display: block;
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -4758,7 +4745,8 @@ aside {
|
|||||||
width: auto !important;
|
width: auto !important;
|
||||||
float: none !important;
|
float: none !important;
|
||||||
padding-left: 0.25em; }
|
padding-left: 0.25em; }
|
||||||
.list.queue-track-list .list-item .added .by {
|
.list.queue-track-list .list-item .added .by,
|
||||||
|
.list.queue-track-list .list-item .added .empty {
|
||||||
display: none; }
|
display: none; }
|
||||||
.list.queue-track-list .list-item .added .from {
|
.list.queue-track-list .list-item .added .from {
|
||||||
padding-left: 14px;
|
padding-left: 14px;
|
||||||
@ -5343,6 +5331,8 @@ main header {
|
|||||||
display: block; }
|
display: block; }
|
||||||
.dropdown-field.no-status-icon .options .option {
|
.dropdown-field.no-status-icon .options .option {
|
||||||
padding-left: 12px; }
|
padding-left: 12px; }
|
||||||
|
.dropdown-field.no-label .label > .text {
|
||||||
|
display: none; }
|
||||||
.dropdown-field .options {
|
.dropdown-field .options {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -4772,11 +4772,14 @@ exports.getQueueMetadata = getQueueMetadata;
|
|||||||
exports.queueMetadataChanged = queueMetadataChanged;
|
exports.queueMetadataChanged = queueMetadataChanged;
|
||||||
exports.addQueueMetadata = addQueueMetadata;
|
exports.addQueueMetadata = addQueueMetadata;
|
||||||
exports.getSnapcast = getSnapcast;
|
exports.getSnapcast = getSnapcast;
|
||||||
|
exports.snapcastServerLoaded = snapcastServerLoaded;
|
||||||
exports.setSnapcastClientName = setSnapcastClientName;
|
exports.setSnapcastClientName = setSnapcastClientName;
|
||||||
exports.setSnapcastClientMute = setSnapcastClientMute;
|
exports.setSnapcastClientMute = setSnapcastClientMute;
|
||||||
exports.setSnapcastClientVolume = setSnapcastClientVolume;
|
exports.setSnapcastClientVolume = setSnapcastClientVolume;
|
||||||
exports.setSnapcastClientLatency = setSnapcastClientLatency;
|
exports.setSnapcastClientLatency = setSnapcastClientLatency;
|
||||||
|
exports.setSnapcastClientGroup = setSnapcastClientGroup;
|
||||||
exports.deleteSnapcastClient = deleteSnapcastClient;
|
exports.deleteSnapcastClient = deleteSnapcastClient;
|
||||||
|
exports.setSnapcastGroupStream = setSnapcastGroupStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions and Action Creators
|
* Actions and Action Creators
|
||||||
@ -4989,6 +4992,13 @@ function getSnapcast() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function snapcastServerLoaded(server) {
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SNAPCAST_SERVER_LOADED',
|
||||||
|
server: server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function setSnapcastClientName(id, name) {
|
function setSnapcastClientName(id, name) {
|
||||||
return {
|
return {
|
||||||
type: 'PUSHER_SET_SNAPCAST_CLIENT_NAME',
|
type: 'PUSHER_SET_SNAPCAST_CLIENT_NAME',
|
||||||
@ -5021,6 +5031,15 @@ function setSnapcastClientLatency(id, latency) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSnapcastClientGroup(id, group_id) {
|
||||||
|
console.log(id, group_id);
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SET_SNAPCAST_CLIENT_GROUP',
|
||||||
|
id: id,
|
||||||
|
group_id: group_id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function deleteSnapcastClient(id) {
|
function deleteSnapcastClient(id) {
|
||||||
return {
|
return {
|
||||||
type: 'PUSHER_DELETE_SNAPCAST_CLIENT',
|
type: 'PUSHER_DELETE_SNAPCAST_CLIENT',
|
||||||
@ -5028,6 +5047,14 @@ function deleteSnapcastClient(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSnapcastGroupStream(id, stream_id) {
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SET_SNAPCAST_GROUP_STREAM',
|
||||||
|
id: id,
|
||||||
|
stream_id: stream_id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
/* 18 */
|
/* 18 */
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
@ -19458,6 +19485,9 @@ var DropdownField = function (_React$Component) {
|
|||||||
if (this.props.no_status_icon) {
|
if (this.props.no_status_icon) {
|
||||||
className += ' no-status-icon';
|
className += ' no-status-icon';
|
||||||
}
|
}
|
||||||
|
if (this.props.no_label) {
|
||||||
|
className += ' no-label';
|
||||||
|
}
|
||||||
if (this.props.button) {
|
if (this.props.button) {
|
||||||
className += ' buttonify';
|
className += ' buttonify';
|
||||||
}
|
}
|
||||||
@ -24492,6 +24522,14 @@ var Track = function (_React$Component) {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "search":
|
||||||
|
var link = _react2.default.createElement(
|
||||||
|
_URILink2.default,
|
||||||
|
{ type: 'search', uri: track.added_from.replace("iris:", "") },
|
||||||
|
'search'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var link = _react2.default.createElement(
|
var link = _react2.default.createElement(
|
||||||
_URILink2.default,
|
_URILink2.default,
|
||||||
@ -24528,7 +24566,7 @@ var Track = function (_React$Component) {
|
|||||||
} else {
|
} else {
|
||||||
var added = _react2.default.createElement(
|
var added = _react2.default.createElement(
|
||||||
'span',
|
'span',
|
||||||
{ className: 'placeholder' },
|
{ className: 'empty' },
|
||||||
'-'
|
'-'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -49459,7 +49497,17 @@ function reducer() {
|
|||||||
return Object.assign({}, pusher, { config: action.config });
|
return Object.assign({}, pusher, { config: action.config });
|
||||||
|
|
||||||
case 'PUSHER_SNAPCAST':
|
case 'PUSHER_SNAPCAST':
|
||||||
return Object.assign({}, pusher, { snapcast_clients: action.snapcast_clients, snapcast_groups: action.snapcast_groups });
|
return Object.assign({}, pusher, {
|
||||||
|
snapcast_streams: action.snapcast_streams,
|
||||||
|
snapcast_groups: action.snapcast_groups,
|
||||||
|
snapcast_clients: action.snapcast_clients
|
||||||
|
});
|
||||||
|
|
||||||
|
case 'PUSHER_SNAPCAST_GROUP_UPDATED':
|
||||||
|
var snapcast_groups = Object.assign({}, pusher.snapcast_groups);
|
||||||
|
var group = snapcast_groups[action.key];
|
||||||
|
snapcast_groups[action.key] = Object.assign({}, group, action.group);
|
||||||
|
return Object.assign({}, pusher, { snapcast_groups: snapcast_groups });
|
||||||
|
|
||||||
case 'PUSHER_SNAPCAST_CLIENT_UPDATED':
|
case 'PUSHER_SNAPCAST_CLIENT_UPDATED':
|
||||||
var snapcast_clients = Object.assign({}, pusher.snapcast_clients);
|
var snapcast_clients = Object.assign({}, pusher.snapcast_clients);
|
||||||
@ -51432,40 +51480,53 @@ var PusherMiddleware = function () {
|
|||||||
**/
|
**/
|
||||||
case 'PUSHER_GET_SNAPCAST':
|
case 'PUSHER_GET_SNAPCAST':
|
||||||
request(store, 'snapcast_instruct', action.data).then(function (response) {
|
request(store, 'snapcast_instruct', action.data).then(function (response) {
|
||||||
var groups = {};
|
store.dispatch(pusherActions.snapcastServerLoaded(response.server));
|
||||||
var clients = {};
|
|
||||||
|
|
||||||
// Loop all the groups
|
|
||||||
for (var i = 0; i < response.server.groups.length; i++) {
|
|
||||||
var group = response.server.groups[i];
|
|
||||||
var clients_ids = [];
|
|
||||||
|
|
||||||
// And now this groups' clients
|
|
||||||
for (var j = 0; j < group.clients.length; j++) {
|
|
||||||
var client = group.clients[j];
|
|
||||||
clients[client.id] = client;
|
|
||||||
clients_ids.push(client.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
groups[group.id] = {
|
|
||||||
id: group.id,
|
|
||||||
muted: group.muted,
|
|
||||||
name: group.name,
|
|
||||||
stream_id: group.stream_id,
|
|
||||||
clients_ids: clients_ids
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
store.dispatch({
|
|
||||||
type: 'PUSHER_SNAPCAST',
|
|
||||||
snapcast_clients: clients,
|
|
||||||
snapcast_groups: groups
|
|
||||||
});
|
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
store.dispatch(coreActions.handleException('Could not get Snapcast server', error, error.message));
|
store.dispatch(coreActions.handleException('Could not get Snapcast server', error, error.message));
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'PUSHER_SNAPCAST_SERVER_LOADED':
|
||||||
|
console.log(action);
|
||||||
|
var groups = {};
|
||||||
|
var clients = {};
|
||||||
|
var streams = {};
|
||||||
|
|
||||||
|
// Loop all the groups
|
||||||
|
for (var i = 0; i < action.server.groups.length; i++) {
|
||||||
|
var group = action.server.groups[i];
|
||||||
|
var clients_ids = [];
|
||||||
|
|
||||||
|
// And now this groups' clients
|
||||||
|
for (var j = 0; j < group.clients.length; j++) {
|
||||||
|
var client = group.clients[j];
|
||||||
|
clients[client.id] = client;
|
||||||
|
clients_ids.push(client.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
groups[group.id] = {
|
||||||
|
id: group.id,
|
||||||
|
muted: group.muted,
|
||||||
|
name: group.name,
|
||||||
|
stream_id: group.stream_id,
|
||||||
|
clients_ids: clients_ids
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop all the streams
|
||||||
|
for (var i = 0; i < action.server.streams.length; i++) {
|
||||||
|
var stream = action.server.streams[i];
|
||||||
|
streams[stream.id] = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
type: 'PUSHER_SNAPCAST',
|
||||||
|
snapcast_clients: clients,
|
||||||
|
snapcast_groups: groups,
|
||||||
|
snapcast_streams: streams
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
case 'PUSHER_SET_SNAPCAST_CLIENT_NAME':
|
case 'PUSHER_SET_SNAPCAST_CLIENT_NAME':
|
||||||
var client = store.getState().pusher.snapcast_clients[action.id];
|
var client = store.getState().pusher.snapcast_clients[action.id];
|
||||||
var data = {
|
var data = {
|
||||||
@ -51572,6 +51633,24 @@ var PusherMiddleware = function () {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'PUSHER_SET_SNAPCAST_CLIENT_GROUP':
|
||||||
|
var group = store.getState().pusher.snapcast_groups[action.group_id];
|
||||||
|
var clients_ids = Object.assign([], group.clients_ids, [action.id]);
|
||||||
|
var data = {
|
||||||
|
method: 'Group.SetClients',
|
||||||
|
params: {
|
||||||
|
id: action.group_id,
|
||||||
|
clients: clients_ids
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request(store, 'snapcast_instruct', data).then(function (response) {
|
||||||
|
store.dispatch(pusherActions.snapcastServerLoaded(response.server));
|
||||||
|
}, function (error) {
|
||||||
|
store.dispatch(coreActions.handleException('Error', error, error.message));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
case 'PUSHER_DELETE_SNAPCAST_CLIENT':
|
case 'PUSHER_DELETE_SNAPCAST_CLIENT':
|
||||||
var data = {
|
var data = {
|
||||||
method: 'Server.DeleteClient',
|
method: 'Server.DeleteClient',
|
||||||
@ -51590,6 +51669,29 @@ var PusherMiddleware = function () {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'PUSHER_SET_SNAPCAST_GROUP_STREAM':
|
||||||
|
var group = store.getState().pusher.snapcast_groups[action.id];
|
||||||
|
var data = {
|
||||||
|
method: 'Group.SetStream',
|
||||||
|
params: {
|
||||||
|
id: action.id,
|
||||||
|
stream_id: action.stream_id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request(store, 'snapcast_instruct', data).then(function (response) {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'PUSHER_SNAPCAST_GROUP_UPDATED',
|
||||||
|
key: action.id,
|
||||||
|
group: {
|
||||||
|
stream_id: action.stream_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, function (error) {
|
||||||
|
store.dispatch(coreActions.handleException('Error', error, error.message));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
// This action is irrelevant to us, pass it on to the next middleware
|
// This action is irrelevant to us, pass it on to the next middleware
|
||||||
default:
|
default:
|
||||||
return next(action);
|
return next(action);
|
||||||
@ -51722,6 +51824,7 @@ var MopidyMiddleware = function () {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'event:trackPlaybackEnded':
|
case 'event:trackPlaybackEnded':
|
||||||
|
// This doesn't fire when it's the last track in the queue... bug in Mopidy?
|
||||||
store.dispatch(mopidyActions.clearCurrentTrack());
|
store.dispatch(mopidyActions.clearCurrentTrack());
|
||||||
store.dispatch(mopidyActions.getTimePosition());
|
store.dispatch(mopidyActions.getTimePosition());
|
||||||
break;
|
break;
|
||||||
@ -68022,7 +68125,7 @@ var Search = function (_React$Component) {
|
|||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'section',
|
'section',
|
||||||
{ className: 'list-wrapper' },
|
{ className: 'list-wrapper' },
|
||||||
_react2.default.createElement(_TrackList2.default, { tracks: tracks, uri: this.props.params.query, show_source_icon: true }),
|
_react2.default.createElement(_TrackList2.default, { tracks: tracks, uri: 'iris:' + this.props.params.query, show_source_icon: true }),
|
||||||
_react2.default.createElement(_LazyLoadListener2.default, { enabled: this.props['tracks_more'] && spotify_search_enabled, loadMore: function loadMore() {
|
_react2.default.createElement(_LazyLoadListener2.default, { enabled: this.props['tracks_more'] && spotify_search_enabled, loadMore: function loadMore() {
|
||||||
return _this2.loadMore('tracks');
|
return _this2.loadMore('tracks');
|
||||||
} })
|
} })
|
||||||
@ -68127,7 +68230,7 @@ var Search = function (_React$Component) {
|
|||||||
var tracks_section = _react2.default.createElement(
|
var tracks_section = _react2.default.createElement(
|
||||||
'section',
|
'section',
|
||||||
{ className: 'list-wrapper' },
|
{ className: 'list-wrapper' },
|
||||||
_react2.default.createElement(_TrackList2.default, { tracks: tracks, uri: this.props.params.query, show_source_icon: true }),
|
_react2.default.createElement(_TrackList2.default, { tracks: tracks, uri: 'iris:' + this.props.params.query, show_source_icon: true }),
|
||||||
_react2.default.createElement(_LazyLoadListener2.default, { loading: this.props['tracks_more'] && spotify_search_enabled, loadMore: function loadMore() {
|
_react2.default.createElement(_LazyLoadListener2.default, { loading: this.props['tracks_more'] && spotify_search_enabled, loadMore: function loadMore() {
|
||||||
return _this2.loadMore('tracks');
|
return _this2.loadMore('tracks');
|
||||||
} })
|
} })
|
||||||
@ -70288,6 +70391,10 @@ var _TextField = __webpack_require__(257);
|
|||||||
|
|
||||||
var _TextField2 = _interopRequireDefault(_TextField);
|
var _TextField2 = _interopRequireDefault(_TextField);
|
||||||
|
|
||||||
|
var _DropdownField = __webpack_require__(40);
|
||||||
|
|
||||||
|
var _DropdownField2 = _interopRequireDefault(_DropdownField);
|
||||||
|
|
||||||
var _helpers = __webpack_require__(1);
|
var _helpers = __webpack_require__(1);
|
||||||
|
|
||||||
var helpers = _interopRequireWildcard(_helpers);
|
var helpers = _interopRequireWildcard(_helpers);
|
||||||
@ -70372,17 +70479,34 @@ var Snapcast = function (_React$Component) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var streams = [];
|
||||||
|
for (var key in this.props.snapcast_streams) {
|
||||||
|
if (this.props.snapcast_streams.hasOwnProperty(key)) {
|
||||||
|
streams.push(this.props.snapcast_streams[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Construct a simple array of our groups index
|
// Construct a simple array of our groups index
|
||||||
var groups = [];
|
var groups = [];
|
||||||
|
var groups_dropdown = [];
|
||||||
for (var group_id in this.props.snapcast_groups) {
|
for (var group_id in this.props.snapcast_groups) {
|
||||||
if (this.props.snapcast_groups.hasOwnProperty(group_id)) {
|
if (this.props.snapcast_groups.hasOwnProperty(group_id)) {
|
||||||
var group = this.props.snapcast_groups[group_id];
|
var group = this.props.snapcast_groups[group_id];
|
||||||
|
|
||||||
|
// Append to our groups dropdown source array
|
||||||
|
groups_dropdown.push({
|
||||||
|
label: group.name ? group.name : group.stream_id,
|
||||||
|
value: group.id
|
||||||
|
});
|
||||||
|
|
||||||
// Merge the group's clients into this group (also as a simple array)
|
// Merge the group's clients into this group (also as a simple array)
|
||||||
var clients = [];
|
var clients = [];
|
||||||
for (var i = 0; i < group.clients_ids.length; i++) {
|
for (var i = 0; i < group.clients_ids.length; i++) {
|
||||||
if (this.props.snapcast_clients.hasOwnProperty(group.clients_ids[i])) {
|
if (this.props.snapcast_clients.hasOwnProperty(group.clients_ids[i])) {
|
||||||
clients.push(this.props.snapcast_clients[group.clients_ids[i]]);
|
var client = this.props.snapcast_clients[group.clients_ids[i]];
|
||||||
|
if (client.connected || this.props.snapcast_show_disconnected_clients) {
|
||||||
|
clients.push(client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70395,104 +70519,156 @@ var Snapcast = function (_React$Component) {
|
|||||||
return _react2.default.createElement(
|
return _react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'snapcast' },
|
{ className: 'snapcast' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'field checkbox' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'input' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'button',
|
||||||
|
{ onClick: function onClick(e) {
|
||||||
|
return _this2.props.pusherActions.getSnapcast();
|
||||||
|
} },
|
||||||
|
'Refresh'
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'label',
|
||||||
|
null,
|
||||||
|
_react2.default.createElement('input', {
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'snapcast_show_disconnected_clients',
|
||||||
|
checked: this.props.snapcast_show_disconnected_clients,
|
||||||
|
onChange: function onChange(e) {
|
||||||
|
return _this2.props.uiActions.set({ snapcast_show_disconnected_clients: !_this2.props.snapcast_show_disconnected_clients });
|
||||||
|
} }),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'span',
|
||||||
|
{ className: 'label' },
|
||||||
|
'Show disconnected clients'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
groups.map(function (group) {
|
groups.map(function (group) {
|
||||||
return _react2.default.createElement(
|
return _react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'list group', key: group.id },
|
{ className: 'group', key: group.id },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'h3',
|
||||||
|
{ className: 'name' },
|
||||||
|
group.name ? group.name : group.stream_id
|
||||||
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'list-item header' },
|
{ className: 'field dropdown' },
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'col name' },
|
{ className: 'name' },
|
||||||
group.name ? group.name : 'Untitled group'
|
'Source'
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'col volume' },
|
{ className: 'input' },
|
||||||
'Volume'
|
|
||||||
),
|
|
||||||
_react2.default.createElement(
|
|
||||||
'div',
|
|
||||||
{ className: 'col latency' },
|
|
||||||
'Latency'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
group.clients.map(function (client) {
|
|
||||||
var name = client.config.name ? client.config.name : client.host.name;
|
|
||||||
return _react2.default.createElement(
|
|
||||||
'div',
|
|
||||||
{ className: 'list-item client', key: client.id },
|
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'select',
|
||||||
{ className: 'col name' },
|
{ onChange: function onChange(e) {
|
||||||
_react2.default.createElement(_TextField2.default, {
|
return _this2.props.pusherActions.setSnapcastGroupStream(group.id, e.target.value);
|
||||||
onChange: function onChange(value) {
|
}, value: group.stream_id },
|
||||||
return _this2.props.pusherActions.setSnapcastClientName(client.id, value);
|
streams.map(function (stream) {
|
||||||
},
|
return _react2.default.createElement(
|
||||||
value: name
|
'option',
|
||||||
}),
|
{ value: stream.id, key: stream.id },
|
||||||
client.connected ? _react2.default.createElement(
|
stream.id,
|
||||||
'span',
|
' (',
|
||||||
{ className: 'status has-tooltip' },
|
stream.status,
|
||||||
_react2.default.createElement(_reactFontawesome2.default, { className: 'green-text', name: 'circle' }),
|
')'
|
||||||
_react2.default.createElement(
|
);
|
||||||
'span',
|
|
||||||
{ className: 'tooltip' },
|
|
||||||
'Connected'
|
|
||||||
)
|
|
||||||
) : _react2.default.createElement(
|
|
||||||
'span',
|
|
||||||
{ className: 'status has-tooltip' },
|
|
||||||
_react2.default.createElement(_reactFontawesome2.default, { className: 'grey-text', name: 'circle' }),
|
|
||||||
_react2.default.createElement(
|
|
||||||
'span',
|
|
||||||
{ className: 'tooltip' },
|
|
||||||
'Not connected'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
_react2.default.createElement(
|
|
||||||
'div',
|
|
||||||
{ className: 'col volume' },
|
|
||||||
_react2.default.createElement(_VolumeControl2.default, {
|
|
||||||
volume: client.config.volume.percent,
|
|
||||||
mute: client.config.volume.muted,
|
|
||||||
onVolumeChange: function onVolumeChange(percent) {
|
|
||||||
return _this2.props.pusherActions.setSnapcastClientVolume(client.id, percent);
|
|
||||||
},
|
|
||||||
onMuteChange: function onMuteChange(mute) {
|
|
||||||
return _this2.props.pusherActions.setSnapcastClientMute(client.id, mute);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
_react2.default.createElement(_TextField2.default, {
|
|
||||||
className: 'tiny',
|
|
||||||
onChange: function onChange(value) {
|
|
||||||
return _this2.props.pusherActions.setSnapcastClientVolume(client.id, parseInt(value));
|
|
||||||
},
|
|
||||||
value: client.config.volume.percent
|
|
||||||
})
|
|
||||||
),
|
|
||||||
_react2.default.createElement(
|
|
||||||
'div',
|
|
||||||
{ className: 'col latency' },
|
|
||||||
_react2.default.createElement(_LatencyControl2.default, {
|
|
||||||
max: '100',
|
|
||||||
value: client.config.latency,
|
|
||||||
onChange: function onChange(value) {
|
|
||||||
return _this2.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value));
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
_react2.default.createElement(_TextField2.default, {
|
|
||||||
className: 'tiny',
|
|
||||||
onChange: function onChange(value) {
|
|
||||||
return _this2.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value));
|
|
||||||
},
|
|
||||||
value: String(client.config.latency)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
})
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'field' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'name' },
|
||||||
|
'Clients'
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'input' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'list clients' },
|
||||||
|
group.clients.map(function (client) {
|
||||||
|
var name = client.config.name ? client.config.name : client.host.name;
|
||||||
|
return _react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'list-item client', key: client.id },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'col name' },
|
||||||
|
_react2.default.createElement(_TextField2.default, {
|
||||||
|
onChange: function onChange(value) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientName(client.id, value);
|
||||||
|
},
|
||||||
|
value: name
|
||||||
|
}),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'tools' },
|
||||||
|
client.connected ? null : _react2.default.createElement(_reactFontawesome2.default, { className: 'disconnected red-text', name: 'plug' }),
|
||||||
|
_react2.default.createElement(_DropdownField2.default, { icon: 'cog', name: 'Group', no_label: true, value: group.id, options: groups_dropdown, handleChange: function handleChange(val) {
|
||||||
|
_this2.props.pusherActions.setSnapcastClientGroup(client.id, group.id);_this2.props.uiActions.hideContextMenu();
|
||||||
|
} })
|
||||||
|
)
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'col volume' },
|
||||||
|
_react2.default.createElement(_VolumeControl2.default, {
|
||||||
|
volume: client.config.volume.percent,
|
||||||
|
mute: client.config.volume.muted,
|
||||||
|
onVolumeChange: function onVolumeChange(percent) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientVolume(client.id, percent);
|
||||||
|
},
|
||||||
|
onMuteChange: function onMuteChange(mute) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientMute(client.id, mute);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_react2.default.createElement(_TextField2.default, {
|
||||||
|
className: 'tiny',
|
||||||
|
onChange: function onChange(value) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientVolume(client.id, parseInt(value));
|
||||||
|
},
|
||||||
|
value: client.config.volume.percent
|
||||||
|
})
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'col latency' },
|
||||||
|
_react2.default.createElement(_LatencyControl2.default, {
|
||||||
|
max: '100',
|
||||||
|
value: client.config.latency,
|
||||||
|
onChange: function onChange(value) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_react2.default.createElement(_TextField2.default, {
|
||||||
|
className: 'tiny',
|
||||||
|
onChange: function onChange(value) {
|
||||||
|
return _this2.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value));
|
||||||
|
},
|
||||||
|
value: String(client.config.latency)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -70506,6 +70682,8 @@ var mapStateToProps = function mapStateToProps(state, ownProps) {
|
|||||||
return {
|
return {
|
||||||
snapcast_enabled: state.pusher.config.snapcast_enabled,
|
snapcast_enabled: state.pusher.config.snapcast_enabled,
|
||||||
pusher_connected: state.pusher.connected,
|
pusher_connected: state.pusher.connected,
|
||||||
|
snapcast_show_disconnected_clients: state.ui.snapcast_show_disconnected_clients !== undefined ? state.ui.snapcast_show_disconnected_clients : false,
|
||||||
|
snapcast_streams: state.pusher.snapcast_streams,
|
||||||
snapcast_groups: state.pusher.snapcast_groups,
|
snapcast_groups: state.pusher.snapcast_groups,
|
||||||
snapcast_clients: state.pusher.snapcast_clients
|
snapcast_clients: state.pusher.snapcast_clients
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -22,7 +22,7 @@
|
|||||||
"start_url": "/iris/index.html",
|
"start_url": "/iris/index.html",
|
||||||
"background_color": "#08d58f",
|
"background_color": "#08d58f",
|
||||||
"theme_color": "#181818",
|
"theme_color": "#181818",
|
||||||
"display": "standalone",
|
"display": "fullscreen",
|
||||||
"app": {
|
"app": {
|
||||||
"background": {}
|
"background": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,12 @@
|
|||||||
<link rel="manifest" href="/iris/assets/manifest.json">
|
<link rel="manifest" href="/iris/assets/manifest.json">
|
||||||
|
|
||||||
<!-- Apple app -->
|
<!-- Apple app -->
|
||||||
<link rel="apple-touch-startup-image" href="/iris/assets/logo-full-512.png">
|
<meta name="apple-mobile-web-app-title" content="Iris" />
|
||||||
<link rel="apple-touch-icon" sizes="192x192" href="/iris/assets/logo-app-192.png">
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<link rel="apple-touch-icon" sizes="512x512" href="/iris/assets/logo-app-512.png">
|
<meta name="apple-mobile-web-app-status-bar-style" content="#121212">
|
||||||
|
<link rel="apple-touch-startup-image" href="/iris/assets/logo-full-512.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="192x192" href="/iris/assets/logo-app-192.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="512x512" href="/iris/assets/logo-app-512.png" />
|
||||||
|
|
||||||
<!-- Raven Sentry -->
|
<!-- Raven Sentry -->
|
||||||
<script src="https://cdn.ravenjs.com/3.17.0/raven.min.js" crossorigin="anonymous"></script>
|
<script src="https://cdn.ravenjs.com/3.17.0/raven.min.js" crossorigin="anonymous"></script>
|
||||||
@ -73,7 +76,7 @@
|
|||||||
|
|
||||||
// Release details
|
// Release details
|
||||||
// These are automatically injected to built HTML
|
// These are automatically injected to built HTML
|
||||||
var build = "1524541685";
|
var build = "1524953170";
|
||||||
var version = "3.17.4";
|
var version = "3.17.4";
|
||||||
|
|
||||||
// Construct the script tag
|
// Construct the script tag
|
||||||
|
|||||||
@ -51,6 +51,9 @@ export default class DropdownField extends React.Component{
|
|||||||
if (this.props.no_status_icon){
|
if (this.props.no_status_icon){
|
||||||
className += ' no-status-icon';
|
className += ' no-status-icon';
|
||||||
}
|
}
|
||||||
|
if (this.props.no_label){
|
||||||
|
className += ' no-label';
|
||||||
|
}
|
||||||
if (this.props.button){
|
if (this.props.button){
|
||||||
className += ' buttonify';
|
className += ' buttonify';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import ArtistSentence from './ArtistSentence'
|
|||||||
import VolumeControl from './Fields/VolumeControl'
|
import VolumeControl from './Fields/VolumeControl'
|
||||||
import LatencyControl from './Fields/LatencyControl'
|
import LatencyControl from './Fields/LatencyControl'
|
||||||
import TextField from './Fields/TextField'
|
import TextField from './Fields/TextField'
|
||||||
|
import DropdownField from './Fields/DropdownField'
|
||||||
|
|
||||||
import * as helpers from '../helpers'
|
import * as helpers from '../helpers'
|
||||||
import * as coreActions from '../services/core/actions'
|
import * as coreActions from '../services/core/actions'
|
||||||
@ -58,12 +59,26 @@ class Snapcast extends React.Component{
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var streams = [];
|
||||||
|
for (var key in this.props.snapcast_streams){
|
||||||
|
if (this.props.snapcast_streams.hasOwnProperty(key)){
|
||||||
|
streams.push(this.props.snapcast_streams[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Construct a simple array of our groups index
|
// Construct a simple array of our groups index
|
||||||
var groups = [];
|
var groups = [];
|
||||||
|
var groups_dropdown = [];
|
||||||
for (var group_id in this.props.snapcast_groups){
|
for (var group_id in this.props.snapcast_groups){
|
||||||
if (this.props.snapcast_groups.hasOwnProperty(group_id)){
|
if (this.props.snapcast_groups.hasOwnProperty(group_id)){
|
||||||
var group = this.props.snapcast_groups[group_id];
|
var group = this.props.snapcast_groups[group_id];
|
||||||
|
|
||||||
|
// Append to our groups dropdown source array
|
||||||
|
groups_dropdown.push({
|
||||||
|
label: (group.name ? group.name : group.stream_id),
|
||||||
|
value: group.id
|
||||||
|
});
|
||||||
|
|
||||||
// Merge the group's clients into this group (also as a simple array)
|
// Merge the group's clients into this group (also as a simple array)
|
||||||
var clients = [];
|
var clients = [];
|
||||||
for (var i = 0; i < group.clients_ids.length; i++){
|
for (var i = 0; i < group.clients_ids.length; i++){
|
||||||
@ -107,65 +122,81 @@ class Snapcast extends React.Component{
|
|||||||
{
|
{
|
||||||
groups.map(group => {
|
groups.map(group => {
|
||||||
return (
|
return (
|
||||||
<div className="list group" key={group.id}>
|
<div className="group" key={group.id}>
|
||||||
<div className="list-item header">
|
<h3 className="name">
|
||||||
<div className="col name">
|
{group.name ? group.name : group.stream_id}
|
||||||
{group.name ? group.name : 'Untitled group'}
|
</h3>
|
||||||
|
<div className="field dropdown">
|
||||||
|
<div className="name">
|
||||||
|
Source
|
||||||
</div>
|
</div>
|
||||||
<div className="col volume">
|
<div className="input">
|
||||||
Volume
|
<select onChange={e => this.props.pusherActions.setSnapcastGroupStream(group.id, e.target.value)} value={group.stream_id}>
|
||||||
</div>
|
{
|
||||||
<div className="col latency">
|
streams.map(stream => {
|
||||||
Latency
|
return (
|
||||||
|
<option value={stream.id} key={stream.id}>
|
||||||
|
{stream.id} ({stream.status})
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field">
|
||||||
|
<div className="name">
|
||||||
|
Clients
|
||||||
|
</div>
|
||||||
|
<div className="input">
|
||||||
|
<div className="list clients">
|
||||||
|
{
|
||||||
|
group.clients.map(client => {
|
||||||
|
var name = client.config.name ? client.config.name : client.host.name;
|
||||||
|
return (
|
||||||
|
<div className="list-item client" key={client.id}>
|
||||||
|
<div className="col name">
|
||||||
|
<TextField
|
||||||
|
onChange={value => this.props.pusherActions.setSnapcastClientName(client.id, value)}
|
||||||
|
value={name}
|
||||||
|
/>
|
||||||
|
<div className="tools">
|
||||||
|
{client.connected ? null : <FontAwesome className="disconnected red-text" name="plug" />}
|
||||||
|
<DropdownField icon="cog" name="Group" no_label value={group.id} options={groups_dropdown} handleChange={val => {this.props.pusherActions.setSnapcastClientGroup(client.id, group.id); this.props.uiActions.hideContextMenu()}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col volume">
|
||||||
|
<VolumeControl
|
||||||
|
volume={client.config.volume.percent}
|
||||||
|
mute={client.config.volume.muted}
|
||||||
|
onVolumeChange={percent => this.props.pusherActions.setSnapcastClientVolume(client.id, percent)}
|
||||||
|
onMuteChange={mute => this.props.pusherActions.setSnapcastClientMute(client.id, mute)}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
className="tiny"
|
||||||
|
onChange={value => this.props.pusherActions.setSnapcastClientVolume(client.id, parseInt(value))}
|
||||||
|
value={client.config.volume.percent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col latency">
|
||||||
|
<LatencyControl
|
||||||
|
max="100"
|
||||||
|
value={client.config.latency}
|
||||||
|
onChange={value => this.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value))}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
className="tiny"
|
||||||
|
onChange={value => this.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value))}
|
||||||
|
value={String(client.config.latency)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
|
||||||
group.clients.map(client => {
|
|
||||||
var name = client.config.name ? client.config.name : client.host.name;
|
|
||||||
return (
|
|
||||||
<div className="list-item client" key={client.id}>
|
|
||||||
<div className="col name">
|
|
||||||
<TextField
|
|
||||||
onChange={value => this.props.pusherActions.setSnapcastClientName(client.id, value)}
|
|
||||||
value={name}
|
|
||||||
/>
|
|
||||||
{client.connected ? <span className="status has-tooltip">
|
|
||||||
<FontAwesome className="green-text" name="circle" />
|
|
||||||
<span className="tooltip">Connected</span>
|
|
||||||
</span> : <span className="status has-tooltip">
|
|
||||||
<FontAwesome className="grey-text" name="circle" />
|
|
||||||
<span className="tooltip">Not connected</span>
|
|
||||||
</span>}
|
|
||||||
</div>
|
|
||||||
<div className="col volume">
|
|
||||||
<VolumeControl
|
|
||||||
volume={client.config.volume.percent}
|
|
||||||
mute={client.config.volume.muted}
|
|
||||||
onVolumeChange={percent => this.props.pusherActions.setSnapcastClientVolume(client.id, percent)}
|
|
||||||
onMuteChange={mute => this.props.pusherActions.setSnapcastClientMute(client.id, mute)}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
className="tiny"
|
|
||||||
onChange={value => this.props.pusherActions.setSnapcastClientVolume(client.id, parseInt(value))}
|
|
||||||
value={client.config.volume.percent}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="col latency">
|
|
||||||
<LatencyControl
|
|
||||||
max="100"
|
|
||||||
value={client.config.latency}
|
|
||||||
onChange={value => this.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value))}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
className="tiny"
|
|
||||||
onChange={value => this.props.pusherActions.setSnapcastClientLatency(client.id, parseInt(value))}
|
|
||||||
value={String(client.config.latency)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -180,6 +211,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
snapcast_enabled: state.pusher.config.snapcast_enabled,
|
snapcast_enabled: state.pusher.config.snapcast_enabled,
|
||||||
pusher_connected: state.pusher.connected,
|
pusher_connected: state.pusher.connected,
|
||||||
snapcast_show_disconnected_clients: (state.ui.snapcast_show_disconnected_clients !== undefined ? state.ui.snapcast_show_disconnected_clients : false),
|
snapcast_show_disconnected_clients: (state.ui.snapcast_show_disconnected_clients !== undefined ? state.ui.snapcast_show_disconnected_clients : false),
|
||||||
|
snapcast_streams: state.pusher.snapcast_streams,
|
||||||
snapcast_groups: state.pusher.snapcast_groups,
|
snapcast_groups: state.pusher.snapcast_groups,
|
||||||
snapcast_clients: state.pusher.snapcast_clients
|
snapcast_clients: state.pusher.snapcast_clients
|
||||||
}
|
}
|
||||||
|
|||||||
@ -203,6 +203,13 @@ export function getSnapcast(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function snapcastServerLoaded(server){
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SNAPCAST_SERVER_LOADED',
|
||||||
|
server: server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function setSnapcastClientName(id, name){
|
export function setSnapcastClientName(id, name){
|
||||||
return {
|
return {
|
||||||
type: 'PUSHER_SET_SNAPCAST_CLIENT_NAME',
|
type: 'PUSHER_SET_SNAPCAST_CLIENT_NAME',
|
||||||
@ -235,6 +242,15 @@ export function setSnapcastClientLatency(id, latency){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setSnapcastClientGroup(id, group_id){
|
||||||
|
console.log(id,group_id);
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SET_SNAPCAST_CLIENT_GROUP',
|
||||||
|
id: id,
|
||||||
|
group_id: group_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteSnapcastClient(id){
|
export function deleteSnapcastClient(id){
|
||||||
return {
|
return {
|
||||||
type: 'PUSHER_DELETE_SNAPCAST_CLIENT',
|
type: 'PUSHER_DELETE_SNAPCAST_CLIENT',
|
||||||
@ -242,3 +258,11 @@ export function deleteSnapcastClient(id){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setSnapcastGroupStream(id, stream_id){
|
||||||
|
return {
|
||||||
|
type: 'PUSHER_SET_SNAPCAST_GROUP_STREAM',
|
||||||
|
id: id,
|
||||||
|
stream_id: stream_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -586,43 +586,7 @@ const PusherMiddleware = (function(){
|
|||||||
request(store, 'snapcast_instruct', action.data)
|
request(store, 'snapcast_instruct', action.data)
|
||||||
.then(
|
.then(
|
||||||
response => {
|
response => {
|
||||||
var groups = {};
|
store.dispatch(pusherActions.snapcastServerLoaded(response.server));
|
||||||
var clients = {};
|
|
||||||
var streams = {};
|
|
||||||
|
|
||||||
// Loop all the groups
|
|
||||||
for (var i = 0; i < response.server.groups.length; i++){
|
|
||||||
var group = response.server.groups[i];
|
|
||||||
var clients_ids = [];
|
|
||||||
|
|
||||||
// And now this groups' clients
|
|
||||||
for (var j = 0; j < group.clients.length; j++){
|
|
||||||
var client = group.clients[j];
|
|
||||||
clients[client.id] = client;
|
|
||||||
clients_ids.push(client.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
groups[group.id] = {
|
|
||||||
id: group.id,
|
|
||||||
muted: group.muted,
|
|
||||||
name: group.name,
|
|
||||||
stream_id: group.stream_id,
|
|
||||||
clients_ids: clients_ids
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop all the streams
|
|
||||||
for (var i = 0; i < response.server.streams.length; i++){
|
|
||||||
var stream = response.server.streams[i];
|
|
||||||
streams[stream.id] = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
store.dispatch({
|
|
||||||
type: 'PUSHER_SNAPCAST',
|
|
||||||
snapcast_clients: clients,
|
|
||||||
snapcast_groups: groups,
|
|
||||||
snapcast_streams: streams
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
store.dispatch(coreActions.handleException(
|
store.dispatch(coreActions.handleException(
|
||||||
@ -634,6 +598,47 @@ const PusherMiddleware = (function(){
|
|||||||
);
|
);
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'PUSHER_SNAPCAST_SERVER_LOADED':
|
||||||
|
console.log(action);
|
||||||
|
var groups = {};
|
||||||
|
var clients = {};
|
||||||
|
var streams = {};
|
||||||
|
|
||||||
|
// Loop all the groups
|
||||||
|
for (var i = 0; i < action.server.groups.length; i++){
|
||||||
|
var group = action.server.groups[i];
|
||||||
|
var clients_ids = [];
|
||||||
|
|
||||||
|
// And now this groups' clients
|
||||||
|
for (var j = 0; j < group.clients.length; j++){
|
||||||
|
var client = group.clients[j];
|
||||||
|
clients[client.id] = client;
|
||||||
|
clients_ids.push(client.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
groups[group.id] = {
|
||||||
|
id: group.id,
|
||||||
|
muted: group.muted,
|
||||||
|
name: group.name,
|
||||||
|
stream_id: group.stream_id,
|
||||||
|
clients_ids: clients_ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop all the streams
|
||||||
|
for (var i = 0; i < action.server.streams.length; i++){
|
||||||
|
var stream = action.server.streams[i];
|
||||||
|
streams[stream.id] = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
type: 'PUSHER_SNAPCAST',
|
||||||
|
snapcast_clients: clients,
|
||||||
|
snapcast_groups: groups,
|
||||||
|
snapcast_streams: streams
|
||||||
|
});
|
||||||
|
break
|
||||||
|
|
||||||
case 'PUSHER_SET_SNAPCAST_CLIENT_NAME':
|
case 'PUSHER_SET_SNAPCAST_CLIENT_NAME':
|
||||||
var client = store.getState().pusher.snapcast_clients[action.id];
|
var client = store.getState().pusher.snapcast_clients[action.id];
|
||||||
var data = {
|
var data = {
|
||||||
@ -772,6 +777,32 @@ const PusherMiddleware = (function(){
|
|||||||
);
|
);
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'PUSHER_SET_SNAPCAST_CLIENT_GROUP':
|
||||||
|
var group = store.getState().pusher.snapcast_groups[action.group_id];
|
||||||
|
var clients_ids = Object.assign([], group.clients_ids, [action.id]);
|
||||||
|
var data = {
|
||||||
|
method: 'Group.SetClients',
|
||||||
|
params: {
|
||||||
|
id: action.group_id,
|
||||||
|
clients: clients_ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request(store, 'snapcast_instruct', data)
|
||||||
|
.then(
|
||||||
|
response => {
|
||||||
|
store.dispatch(pusherActions.snapcastServerLoaded(response.server));
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
store.dispatch(coreActions.handleException(
|
||||||
|
'Error',
|
||||||
|
error,
|
||||||
|
error.message
|
||||||
|
));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break
|
||||||
|
|
||||||
case 'PUSHER_DELETE_SNAPCAST_CLIENT':
|
case 'PUSHER_DELETE_SNAPCAST_CLIENT':
|
||||||
var data = {
|
var data = {
|
||||||
method: 'Server.DeleteClient',
|
method: 'Server.DeleteClient',
|
||||||
@ -798,6 +829,37 @@ const PusherMiddleware = (function(){
|
|||||||
);
|
);
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'PUSHER_SET_SNAPCAST_GROUP_STREAM':
|
||||||
|
var group = store.getState().pusher.snapcast_groups[action.id];
|
||||||
|
var data = {
|
||||||
|
method: 'Group.SetStream',
|
||||||
|
params: {
|
||||||
|
id: action.id,
|
||||||
|
stream_id: action.stream_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request(store, 'snapcast_instruct', data)
|
||||||
|
.then(
|
||||||
|
response => {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'PUSHER_SNAPCAST_GROUP_UPDATED',
|
||||||
|
key: action.id,
|
||||||
|
group: {
|
||||||
|
stream_id: action.stream_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
store.dispatch(coreActions.handleException(
|
||||||
|
'Error',
|
||||||
|
error,
|
||||||
|
error.message
|
||||||
|
));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break
|
||||||
|
|
||||||
// This action is irrelevant to us, pass it on to the next middleware
|
// This action is irrelevant to us, pass it on to the next middleware
|
||||||
default:
|
default:
|
||||||
return next(action);
|
return next(action);
|
||||||
|
|||||||
@ -55,7 +55,17 @@ export default function reducer(pusher = {}, action){
|
|||||||
return Object.assign({}, pusher, { config: action.config });
|
return Object.assign({}, pusher, { config: action.config });
|
||||||
|
|
||||||
case 'PUSHER_SNAPCAST':
|
case 'PUSHER_SNAPCAST':
|
||||||
return Object.assign({}, pusher, { snapcast_clients: action.snapcast_clients, snapcast_groups: action.snapcast_groups });
|
return Object.assign({}, pusher, {
|
||||||
|
snapcast_streams: action.snapcast_streams,
|
||||||
|
snapcast_groups: action.snapcast_groups,
|
||||||
|
snapcast_clients: action.snapcast_clients
|
||||||
|
});
|
||||||
|
|
||||||
|
case 'PUSHER_SNAPCAST_GROUP_UPDATED':
|
||||||
|
var snapcast_groups = Object.assign({}, pusher.snapcast_groups);
|
||||||
|
var group = snapcast_groups[action.key];
|
||||||
|
snapcast_groups[action.key] = Object.assign({}, group, action.group);
|
||||||
|
return Object.assign({}, pusher, { snapcast_groups: snapcast_groups });
|
||||||
|
|
||||||
case 'PUSHER_SNAPCAST_CLIENT_UPDATED':
|
case 'PUSHER_SNAPCAST_CLIENT_UPDATED':
|
||||||
var snapcast_clients = Object.assign({}, pusher.snapcast_clients);
|
var snapcast_clients = Object.assign({}, pusher.snapcast_clients);
|
||||||
|
|||||||
@ -33,6 +33,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.no-label {
|
||||||
|
.label > .text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.options {
|
.options {
|
||||||
color: $black;
|
color: $black;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -13,7 +13,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 -10px -1px -10px;
|
margin: 0 -10px -1px -10px;
|
||||||
padding: 14px 30px 13px 10px;
|
padding: 14px 30px 13px 10px;
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.05);
|
border-bottom: 1px solid rgba(255,255,255,0.05);
|
||||||
border-top: 1px solid rgba(255,255,255,0.05);
|
border-top: 1px solid rgba(255,255,255,0.05);
|
||||||
@ -96,6 +95,8 @@
|
|||||||
|
|
||||||
&.track-list {
|
&.track-list {
|
||||||
.list-item {
|
.list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name {
|
&.name {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
@ -142,6 +143,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.playlist-list .list-item {
|
&.playlist-list .list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name {
|
&.name {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
@ -159,6 +162,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.album-list .list-item {
|
&.album-list .list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name,
|
&.name,
|
||||||
&.artists {
|
&.artists {
|
||||||
@ -175,6 +180,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.library-local-album-list .list-item{
|
&.library-local-album-list .list-item{
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name,
|
&.name,
|
||||||
&.artists {
|
&.artists {
|
||||||
@ -187,6 +194,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.artist-list .list-item {
|
&.artist-list .list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name {
|
&.name {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
@ -199,6 +208,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.queue-track-list {
|
&.queue-track-list {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.list-item {
|
.list-item {
|
||||||
padding-right: 60px;
|
padding-right: 60px;
|
||||||
.col {
|
.col {
|
||||||
@ -230,6 +241,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.queue-history-track-list .list-item {
|
&.queue-history-track-list .list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
&.name {
|
&.name {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
@ -243,6 +256,7 @@
|
|||||||
|
|
||||||
&.related-artist-list {
|
&.related-artist-list {
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.artist {
|
.artist {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@ -1,79 +1,60 @@
|
|||||||
|
|
||||||
.snapcast {
|
.snapcast {
|
||||||
|
|
||||||
.group.list {
|
.group {
|
||||||
padding: 0 10px;
|
|
||||||
|
|
||||||
&:not(:first-child){
|
&:not(:first-child){
|
||||||
padding-top: 15px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item {
|
.clients {
|
||||||
padding: 20px 0 0 0;
|
padding: 0 10px;
|
||||||
|
|
||||||
&:not(.header){
|
.client {
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .name {
|
|
||||||
width: 40%;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.status {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 2;
|
|
||||||
padding: 12px;
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .volume {
|
|
||||||
width: 28%;
|
|
||||||
padding-left: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .latency {
|
|
||||||
width: 28%;
|
|
||||||
padding-left: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.header {
|
|
||||||
padding-top: 0;
|
|
||||||
vertical-align: bottom;
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
font-size: 14px;
|
|
||||||
color: $white;
|
|
||||||
text-transform: none;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.client {
|
|
||||||
@include clearfix();
|
@include clearfix();
|
||||||
padding: 20px 0 0 0;
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
&:not(:first-child){
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
& > .name {
|
& > .name {
|
||||||
|
width: 40%;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.disconnected {
|
||||||
|
padding: 12px 0;
|
||||||
|
cursor: default;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .volume {
|
||||||
|
width: 28%;
|
||||||
|
padding-left: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .latency {
|
||||||
|
width: 28%;
|
||||||
|
padding-left: 2%;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .volume,
|
& > .volume,
|
||||||
@ -137,35 +118,25 @@
|
|||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@include responsive($bp_medium){
|
@include responsive($bp_medium){
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
|
||||||
padding-left: 0 !important;
|
.col {
|
||||||
padding-right: 0 !important;
|
@include clearfix();
|
||||||
|
float: none !important;
|
||||||
|
width: auto !important;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
&.header {
|
&:not(.header){
|
||||||
display: block;
|
line-height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
.volume,
|
&.volume {
|
||||||
.latency {
|
padding-bottom: 20px !important;
|
||||||
display: none !important;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.col {
|
|
||||||
@include clearfix();
|
|
||||||
float: none !important;
|
|
||||||
width: auto !important;
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
|
|
||||||
&:not(.header){
|
|
||||||
line-height: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.volume {
|
|
||||||
padding-bottom: 20px !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user