UNPKG

@larva.io/webcomponents

Version:

Fentrica SmartUnits WebComponents package

687 lines (686 loc) 26.3 kB
/*! * (C) Fentrica http://fentrica.com - Seee LICENSE.md */ import { Host, h } from "@stencil/core"; import has from "lodash-es/has"; import { createColorClasses } from "../../utils/theme"; import Swiper from "swiper"; import { Pagination, Manipulation } from "swiper/modules"; import { createNotify } from "../internal/notify/notify-controller"; import { createVideoModal } from "../internal/video-modal/video-modal-controller"; import { Camera, DEFAULT_UPLINK } from "./camera"; export class LarRTSPH264MJPEG { constructor() { /** * Hide camera names top of streams */ this.hideCameraNames = false; /** * Hide node titles */ this.hideTitles = false; /** * Is logging for this component enabled (lar-log subcomponent loaded) */ this.log = false; /** * Use upstream proxy for cameras */ this.useUplinkProxy = true; /** * Node size */ this.nodeSize = 'default'; /////// LarvaNode base properties and events - end this.loading = true; this.showPager = false; this.cameras = []; } normalizeSwiperOptions() { const swiperOptions = { modules: [Pagination, Manipulation], effect: 'slide', direction: 'horizontal', initialSlide: 0, loop: false, parallax: false, slidesPerView: 1, spaceBetween: 5, speed: 300, touchEventsTarget: 'container', autoplay: false, pagination: { el: this.paginationEl, type: 'bullets', bulletElement: 'span', dynamicBullets: false, clickable: true, hideOnClick: false, }, }; return swiperOptions; } componentWillLoad() { this.close(); // dynamic update this.videoElementLoading = this.videoElementLoading.bind(this); if (!this.server && !this.useUplinkProxy) { // we dont have to use uplink proxy and we dont have device url defined; generate from current host this.server = Camera.getLocalVideoServer(); } else if (!this.server) { // we do have to use uplink, but no server defined, use default this.server = DEFAULT_UPLINK; } } componentDidLoad() { const el = this.el.shadowRoot || this.el; const swiperel = el.querySelector('.swiper'); const swiperOptions = this.normalizeSwiperOptions(); this.swiper = new Swiper(swiperel, swiperOptions); // start stream if slide shown this.swiper.on('slideChange', () => this.startActiveSlideStream()); this.output.emit(); // read camera list } disconnectedCallback() { try { this.close(); } catch (err) { console.warn(err); } } /** * Larva error input */ async error(data, timeout = 5000) { let msg; if (typeof data === 'string') { msg = data; } else if (data && data.message && typeof data.message === 'string') { msg = data.message; } else { msg = 'error_messages.UNKNOWN_ERROR'; } const translate = h("lar-translate", { t: msg }); const notify = await createNotify({ message: translate, color: 'danger', autoHide: timeout }); await notify.present(); this.loading = false; } /** * Input Larva event message (see above) */ async input(data) { var _a; const el = this.el.shadowRoot || this.el; if (has(data, 'cameras')) { this.closeCameras(); const cameras = Array.isArray(data.cameras) ? data.cameras : []; this.cameras = cameras.map(camera => new Camera(camera, this.server)); this.showPager = this.cameras.length > 1; this.updateSwiper(); } else if (has(data, 'upstream')) { // asked upstream ready message // start camerastream via uplink proxy await ((_a = this.cameras.find(cam => cam.wsurl === data.upstream)) === null || _a === void 0 ? void 0 : _a.open().catch(err => this.error(err))); } } close() { var _a, _b, _c, _d; this.closeCameras(); (_a = this.swiper) === null || _a === void 0 ? void 0 : _a.off('click'); (_b = this.swiper) === null || _b === void 0 ? void 0 : _b.off('slideChange'); (_c = this.swiper) === null || _c === void 0 ? void 0 : _c.removeAllSlides(); (_d = this.swiper) === null || _d === void 0 ? void 0 : _d.destroy(); } closeCameras() { this.cameras.forEach(camera => camera.close()); // close all cameras this.cameras = []; } async openActiveSlideCameraModal() { var _a, _b, _c; try { if (!((_a = this.swiper) === null || _a === void 0 ? void 0 : _a.activeIndex) === undefined) { throw new Error('Swiper not found'); } const slide = (_b = this.swiper) === null || _b === void 0 ? void 0 : _b.slides[(_c = this.swiper) === null || _c === void 0 ? void 0 : _c.activeIndex]; const element = slide === null || slide === void 0 ? void 0 : slide.querySelector('canvas,video'); const cameraId = element === null || element === void 0 ? void 0 : element.getAttribute(Camera.elementCameraIdAttribute); if (!cameraId) { throw new Error('Camera ID not found'); } const camera = this.cameras.find(cam => cam.id === cameraId); if (camera && !camera.loading) { camera.volume(); const modal = await createVideoModal({ color: this.colorModal || this.color, mainTitle: camera.options.name, onLarmodalwillpresent: () => { this.willPresent.emit(); }, onLarmodaldidpresent: () => { this.didPresent.emit(); }, onLarmodalwilldismiss: () => { this.willDismiss.emit(); camera.mute(); slide.appendChild(camera.$el); }, onLarmodaldiddismiss: () => { this.didDismiss.emit(); }, }); modal.present(camera.$el); } else { throw new Error('Camera not found'); } } catch (err) { console.warn(err); } } videoElementLoading(event) { var _a; this.loading = event.detail; // tslint:disable-next-line: no-unbound-method (_a = this.loadingListenerElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('larvideoloading', this.videoElementLoading); this.loadingListenerElement = undefined; } startActiveSlideStream() { var _a, _b, _c, _d, _e; try { // tslint:disable-next-line: no-unbound-method (_a = this.loadingListenerElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('larvideoloading', this.videoElementLoading); this.loadingListenerElement = undefined; if (!((_b = this.swiper) === null || _b === void 0 ? void 0 : _b.activeIndex) === undefined) { throw new Error('Swiper not found'); } const slide = (_c = this.swiper) === null || _c === void 0 ? void 0 : _c.slides[(_d = this.swiper) === null || _d === void 0 ? void 0 : _d.activeIndex]; const element = slide === null || slide === void 0 ? void 0 : slide.querySelector('canvas,video'); const cameraId = element === null || element === void 0 ? void 0 : element.getAttribute(Camera.elementCameraIdAttribute); if (!cameraId) { throw new Error('Camera ID not found'); } const camera = this.cameras.find(cam => cam.id === cameraId); this.loading = camera.loading; if (this.loading) { this.loadingListenerElement = camera.$el; // tslint:disable-next-line: no-unbound-method (_e = this.loadingListenerElement) === null || _e === void 0 ? void 0 : _e.addEventListener('larvideoloading', this.videoElementLoading); } if (camera && !camera.opened) { if (this.useUplinkProxy === true) { // we need to use uplinx proxy, ask for upstream this.output.emit({ upstream: camera.wsurl }); } else if (camera) { // start streamming right away camera.open().catch(err => this.error(err)); } else { throw new Error('Camera not found from list'); } } } catch (err) { console.warn(err); } } updateSwiper() { var _a, _b, _c, _d, _e; const slides = this.cameras.map(camera => { const container = document.createElement('div'); const title = document.createElement('div'); container.className = 'swiper-slide'; title.className = 'swiper-slide-title'; title.innerHTML = camera.options.name; container.appendChild(camera.$el); container.appendChild(title); return container; }); (_a = this.swiper) === null || _a === void 0 ? void 0 : _a.removeAllSlides(); if (slides.length > 0) { (_b = this.swiper) === null || _b === void 0 ? void 0 : _b.appendSlide(slides); this.startActiveSlideStream(); } (_c = this.swiper) === null || _c === void 0 ? void 0 : _c.update(); (_e = (_d = this.swiper) === null || _d === void 0 ? void 0 : _d.pagination) === null || _e === void 0 ? void 0 : _e.update(); } render() { const iconSmall = this.loading ? h("lar-icon", { color: this.colorIconSmall || '', icon: "loading" }) : undefined; return (h(Host, { key: 'bb864fb81d94e7a92d44159d7b6a334982ac8adc', class: createColorClasses(this.color) }, this.nodeSize === 'small' && h("h3", { key: 'e7822cba3b328cc5bd4f76a43b2c396e6d8ff037' }, "Camera small node not available"), this.nodeSize !== 'small' && h("div", { key: '29e0744ba5ee8fc9d7f6b65356438f2e3b9e89bb', class: "lar-node-box", onClick: () => this.openActiveSlideCameraModal() }, h("div", { key: 'f30d5883c1444d015441b3b4e4b3e6c588f7cad1', class: "swiper" }, h("div", { key: 'e863204ec51b748675d5fab315728d336027eac7', class: "swiper-wrapper" }), h("div", { key: '0822f0e16e34a27d08aa7c16bfbe4d55c8e4c580', class: { 'swiper-pagination': true, 'swiper-pagination-hidden': !this.showPager }, ref: el => this.paginationEl = el })), iconSmall && h("div", { key: '740ffd54190c941c8343ceafdda8560091b8e264', class: "lar-icon-small" }, iconSmall)))); } static get is() { return "lar-rtsp-h264-mjpeg"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["rtsp-h264-mjpeg.scss"] }; } static get styleUrls() { return { "$": ["rtsp-h264-mjpeg.css"] }; } static get properties() { return { "color": { "type": "string", "mutable": false, "complexType": { "original": "Color", "resolved": "string", "references": { "Color": { "location": "import", "path": "../../interface", "id": "src/interface.d.ts::Color" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "The color to use from your application's color palette.\nDetrouble options are: `\"primary\"`, `\"secondary\"`, `\"tertiary\"`, `\"success\"`, `\"warning\"`, `\"danger\"`, `\"light\"`, `\"medium\"`, and `\"dark\"`." }, "getter": false, "setter": false, "reflect": false, "attribute": "color" }, "colorModal": { "type": "string", "mutable": false, "complexType": { "original": "Color", "resolved": "string", "references": { "Color": { "location": "import", "path": "../../interface", "id": "src/interface.d.ts::Color" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "The color to use from your application's color palette for Components modal window." }, "getter": false, "setter": false, "reflect": false, "attribute": "color-modal" }, "colorIconSmall": { "type": "string", "mutable": false, "complexType": { "original": "Color", "resolved": "string", "references": { "Color": { "location": "import", "path": "../../interface", "id": "src/interface.d.ts::Color" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "The color to use from your application's color palette for small icon" }, "getter": false, "setter": false, "reflect": false, "attribute": "color-icon-small" }, "hideCameraNames": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Hide camera names top of streams" }, "getter": false, "setter": false, "reflect": false, "attribute": "hide-camera-names", "defaultValue": "false" }, "hideTitles": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Hide node titles" }, "getter": false, "setter": false, "reflect": false, "attribute": "hide-titles", "defaultValue": "false" }, "supTitle": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Component superscript title" }, "getter": false, "setter": false, "reflect": false, "attribute": "sup-title" }, "subTitle": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Component subtitle" }, "getter": false, "setter": false, "reflect": false, "attribute": "sub-title" }, "log": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Is logging for this component enabled (lar-log subcomponent loaded)" }, "getter": false, "setter": false, "reflect": false, "attribute": "log", "defaultValue": "false" }, "useUplinkProxy": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Use upstream proxy for cameras" }, "getter": false, "setter": false, "reflect": false, "attribute": "use-uplink-proxy", "defaultValue": "true" }, "server": { "type": "string", "mutable": true, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": true, "optional": false, "docs": { "tags": [], "text": "server for cameras" }, "getter": false, "setter": false, "reflect": false, "attribute": "server" }, "mainTitle": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": true, "optional": false, "docs": { "tags": [], "text": "Component main title" }, "getter": false, "setter": false, "reflect": false, "attribute": "main-title" }, "nodeSize": { "type": "string", "mutable": false, "complexType": { "original": "Size", "resolved": "\"default\" | \"small\"", "references": { "Size": { "location": "import", "path": "../../interface", "id": "src/interface.d.ts::Size" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "Node size" }, "getter": false, "setter": false, "reflect": false, "attribute": "node-size", "defaultValue": "'default'" } }; } static get states() { return { "loading": {}, "showPager": {} }; } static get events() { return [{ "method": "output", "name": "output", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "see", "text": "{@link ../readme.md} chapter \"Components input and output\" for further information." }], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "request", "name": "request", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "see", "text": "{@link ../readme.md} chapter \"Sub-Components requests and responses\" for further information." }], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "willPresent", "name": "larnodewillpresent", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted before the modal has presented." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "didPresent", "name": "larnodedidpresent", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted after the modal has presented." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "willDismiss", "name": "larnodewilldismiss", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted before the modal has dismissed." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "didDismiss", "name": "larnodediddismiss", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted after the modal has dismissed." }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get methods() { return { "error": { "complexType": { "signature": "(data: any, timeout?: number) => Promise<void>", "parameters": [{ "name": "data", "type": "any", "docs": "" }, { "name": "timeout", "type": "number", "docs": "" }], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Larva error input", "tags": [] } }, "input": { "complexType": { "signature": "(data: DataIn) => Promise<void>", "parameters": [{ "name": "data", "type": "DataIn", "docs": "" }], "references": { "Promise": { "location": "global", "id": "global::Promise" }, "DataIn": { "location": "import", "path": "./rtsp-h264-mjpeg-interface", "id": "src/components/rtsp-h264-mjpeg/rtsp-h264-mjpeg-interface.tsx::DataIn" } }, "return": "Promise<void>" }, "docs": { "text": "Input Larva event message (see above)", "tags": [] } } }; } static get elementRef() { return "el"; } } //# sourceMappingURL=rtsp-h264-mjpeg.js.map