nodecg
Version:
Dynamic broadcast graphics rendered in a browser
148 lines (125 loc) • 3.57 kB
text/typescript
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js";
import "@polymer/paper-dialog/paper-dialog.js";
import "@polymer/paper-toast/paper-toast.js";
import "@polymer/paper-slider/paper-slider.js";
import "./ncg-sound-cue";
import * as Polymer from "@polymer/polymer";
import type { NodeCG as NCGTypes } from "../../../../types/nodecg";
import type { NcgSoundCue } from "./ncg-sound-cue";
class NcgSounds extends Polymer.PolymerElement {
static get template() {
return Polymer.html`
<style include="nodecg-theme">
:host {
@apply --layout-flex-none;
@apply --layout-self-stretch;
@apply --layout-vertical;
display: block;
max-width: 600px;
white-space: nowrap;
width: 100%;
}
#bundleFaderContainer {
@apply --layout-horizontal;
align-items: center;
background-color: #525F78;
}
#bundleFaderContainer > span {
@apply --paper-font-title;
min-width: 166px; /* same width as "Master Fader" label */
flex-grow: 1;
flex-shrink: 0;
overflow: hidden;
text-overflow: ellipsis;
}
#bundleFader {
flex-shrink: 1;
--paper-slider-input: {
width: 80px;
};
}
#cues {
background-color: #2F3A4F;
padding-bottom: 8px;
}
.card-content {
padding: 0;
}
</style>
<paper-card id="card" heading\$="[[bundleName]]">
<div class="card-content">
<div id="bundleFaderContainer">
<span>Bundle Fader</span>
<paper-slider id="bundleFader" min="0" max="100" step="1" on-change="_onBundleFaderChange" editable=""></paper-slider>
</div>
<div id="cues"></div>
</div>
</paper-card>
`;
}
static get is() {
return "ncg-sounds";
}
static get properties() {
return {
bundleName: {
type: String,
reflectToAttribute: true,
},
soundCues: Array,
};
}
override ready(): void {
super.ready();
const cueElsByName: Record<string, NcgSoundCue> = {};
this.bundleFaderRep = NodeCG.Replicant<number>(
`volume:${this.bundleName}`,
"_sounds",
);
const cuesRep = NodeCG.Replicant<NCGTypes.SoundCue[]>(
"soundCues",
this.bundleName,
);
this.bundleFaderRep.on("change", (newVal: number) => {
this.$.bundleFader.value = newVal;
});
cuesRep.on("change", (newVal) => {
if (!newVal) {
return;
}
// Update (or create) the ncg-sound-cue element for every cue in the Replicant.
newVal.forEach((cue) => {
if (!cueElsByName[cue.name]) {
cueElsByName[cue.name] = document.createElement(
"ncg-sound-cue",
) as NcgSoundCue;
this.$.cues.appendChild(cueElsByName[cue.name]);
}
cueElsByName[cue.name]!.name = cue.name;
cueElsByName[cue.name]!.assignable = cue.assignable;
cueElsByName[cue.name]!.defaultFile = cue.defaultFile;
cueElsByName[cue.name]!.file = cue.file;
cueElsByName[cue.name]!.volume = cue.volume;
cueElsByName[cue.name]!._cueRef = cue;
cueElsByName[cue.name]!.bundleName = this.bundleName; // Must be last
});
// Remove cueEls that belong to soundCues that no longer exist.
for (const name in cueElsByName) {
if (!{}.hasOwnProperty.call(cueElsByName, name)) {
continue;
}
const cueEl = cueElsByName[name]!;
const index = newVal.findIndex((cue) => cue.name === cueEl.name);
if (index < 0) {
this.$.cues.removeChild(cueEl);
delete cueElsByName[name];
}
}
});
}
_onBundleFaderChange(e: any) {
this.bundleFaderRep.value = e.target.value;
}
}
customElements.define("ncg-sounds", NcgSounds);