UNPKG

@nent/core

Version:

Functional elements to add routing, data-binding, dynamic HTML, declarative actions, audio, video, and so much more. Supercharge static HTML files into web apps without script or builds.

266 lines (265 loc) 8.27 kB
/*! * NENT 2022 */ import { Component, Element, h, Host, Prop, State, } from '@stencil/core'; import { actionBus, eventBus } from '../../services/actions'; import { debugIf } from '../../services/common/logging'; import { commonState, onCommonStateChange, } from '../../services/common/state'; import { getDataProvider } from '../../services/data/factory'; import { AudioActionListener } from './services/actions'; import { audioState, onAudioStateChange } from './services/state'; /** * Use this element only once per page to enable audio features. * It will add a CDN reference to Howler.js: * <https://cdn.jsdelivr.net/npm/howler@2.2.3/dist/howler.core.min.js> * * @system audio * @extension actions * @extension provider * */ export class Audio { constructor() { this.loaded = false; this.error = null; this.stats = { m: 0, ml: 0, mq: 0, s: 0, sl: 0, }; /** * The Howler.js Script Reference */ this.howlerVersion = '2.2.3'; /** * The display mode enabled shows player state and stats. * No track information or duration is to be displayed. */ this.display = false; /** * Use debug for verbose logging. Useful for figuring * things out. */ this.debug = false; /** * Experimental support for providing audio-data in the * data-provider system. */ this.dataProvider = false; } enableAudio() { commonState.audioEnabled = true; } async componentWillLoad() { debugIf(this.debug, 'n-audio: loading'); audioState.debug = this.debug; if (audioState.hasAudioComponent) { this.error = `Duplicate Audio Player`; return; } if (commonState.dataEnabled) { const storage = (await getDataProvider('storage')); const storedValue = await (storage === null || storage === void 0 ? void 0 : storage.get('audio-enabled')); if (storedValue) { commonState.audioEnabled = storedValue != 'false'; } audioState.muted = (await (storage === null || storage === void 0 ? void 0 : storage.get('audio-muted'))) == 'true'; this.audioStateSubscription = onAudioStateChange('muted', async (m) => { await (storage === null || storage === void 0 ? void 0 : storage.set('audio-muted', m.toString())); }); this.commonStateSubscription = onCommonStateChange('audioEnabled', async (m) => { await (storage === null || storage === void 0 ? void 0 : storage.set('audio-enabled', m.toString())); }); } } registerServices() { if (this.loaded) return; debugIf(this.debug, `n-audio: loading listener`); this.actions = new AudioActionListener(window, eventBus, actionBus, this.dataProvider, this.debug); this.actionSubscription = this.actions.changed.on('changed', () => { this.updateState(); }); audioState.hasAudioComponent = true; this.loaded = true; } updateState() { var _a, _b, _c, _d, _e; this.stats = { m: ((_a = this.actions) === null || _a === void 0 ? void 0 : _a.music.active) ? 1 : 0, ml: ((_b = this.actions) === null || _b === void 0 ? void 0 : _b.music.loader.items.length) || 0, mq: ((_c = this.actions) === null || _c === void 0 ? void 0 : _c.music.queue.items.length) || 0, s: ((_d = this.actions) === null || _d === void 0 ? void 0 : _d.sound.active) ? 1 : 0, sl: ((_e = this.actions) === null || _e === void 0 ? void 0 : _e.sound.loader.items.length) || 0, }; } Error() { return (h(Host, { hidden: !this.display }, h("div", null, h("p", { class: "error" }, this.error)))); } Disabled() { return (h(Host, { hidden: !this.display }, h("div", null, h("p", null, "Audio Disabled"), h("button", { onClick: () => { this.enableAudio(); } }, "Enable")))); } Audio() { if (!this.display) return null; return (h("div", null, h("p", null, "Audio ", this.actions.isPlaying() ? 'Playing' : 'Ready'), h("span", { title: "m=music s=sound l=loaded q=queued" }, "M:", this.stats.m, "\u00A0MQ:", this.stats.mq, "\u00A0ML:", this.stats.ml, "\u00A0S:", this.stats.s, "\u00A0SL:", this.stats.sl))); } NoAudio() { if (!this.display) return null; return (h("div", null, h("p", null, "No Audio"))); } render() { var _a; if (this.error) return this.Error(); if (!commonState.audioEnabled) return this.Disabled(); return (h(Host, { hidden: !this.display }, h("n-content-reference", { inline: true, onReferenced: () => { this.registerServices(); }, "script-src": `https://cdn.jsdelivr.net/npm/howler@${this.howlerVersion}/dist/howler.core.min.js` }), ((_a = this.actions) === null || _a === void 0 ? void 0 : _a.hasAudio()) ? this.Audio() : this.NoAudio())); } disconnectedCallback() { var _a, _b, _c, _d, _e; audioState.hasAudioComponent = false; (_a = this.stateSubscription) === null || _a === void 0 ? void 0 : _a.call(this); (_b = this.actionSubscription) === null || _b === void 0 ? void 0 : _b.call(this); (_c = this.audioStateSubscription) === null || _c === void 0 ? void 0 : _c.call(this); (_d = this.commonStateSubscription) === null || _d === void 0 ? void 0 : _d.call(this); (_e = this.actions) === null || _e === void 0 ? void 0 : _e.destroy(); } static get is() { return "n-audio"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["audio.css"] }; } static get styleUrls() { return { "$": ["audio.css"] }; } static get properties() { return { "actions": { "type": "unknown", "mutable": true, "complexType": { "original": "AudioActionListener", "resolved": "AudioActionListener | undefined", "references": { "AudioActionListener": { "location": "import", "path": "./services/actions" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "A reference to the action listener for testing." } }, "howlerVersion": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The Howler.js Script Reference" }, "attribute": "howler-version", "reflect": false, "defaultValue": "'2.2.3'" }, "display": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The display mode enabled shows player state and stats.\nNo track information or duration is to be displayed." }, "attribute": "display", "reflect": false, "defaultValue": "false" }, "debug": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Use debug for verbose logging. Useful for figuring\nthings out." }, "attribute": "debug", "reflect": false, "defaultValue": "false" }, "dataProvider": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Experimental support for providing audio-data in the\ndata-provider system." }, "attribute": "data-provider", "reflect": false, "defaultValue": "false" } }; } static get states() { return { "loaded": {}, "error": {}, "stats": {} }; } static get elementRef() { return "el"; } }