diff --git a/custom_components/browser_mod/browser_mod.js b/custom_components/browser_mod/browser_mod.js index b498437..2f25c05 100644 --- a/custom_components/browser_mod/browser_mod.js +++ b/custom_components/browser_mod/browser_mod.js @@ -1 +1,56 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);let o=function(){if(window.fully&&"function"==typeof fully.getDeviceId)return fully.getDeviceId();if(!localStorage["lovelace-player-device-id"]){const e=()=>Math.floor(1e5*(1+Math.random())).toString(16).substring(1);localStorage["lovelace-player-device-id"]=`${e()}${e()}-${e()}${e()}`}return localStorage["lovelace-player-device-id"]}();window.browser_mod=new class{constructor(){window.hassConnection.then(e=>this.connect(e.conn)),this.player=new Audio,this.player.addEventListener("ended",this.update.bind(this)),this.player.addEventListener("play",this.update.bind(this)),this.player.addEventListener("pause",this.update.bind(this)),this.player.addEventListener("volumechange",this.update.bind(this))}connect(e){console.log("Connection opened. Connecting to browser_mod"),this.conn=e,e.subscribeMessage(e=>this.callback(e),{type:"browser_mod/connect",deviceID:o}),console.log("Connected"),console.log(this.connection)}callback(e){switch(console.log("Got ws message"),console.log(e),e.command){case"update":this.update(e);break;case"play":this.play(e);break;case"pause":this.pause(e);break;case"stop":this.stop(e);break;case"set_volume":this.set_volume(e);break;case"mute":this.mute(e)}}get player_state(){return this.player.src?this.player.ended?"stopped":this.player.paused?"paused":"playing":"stopped"}play(e){const t=e.media_content_id;t&&(this.player.src=t),this.player.play()}pause(e){this.player.pause()}stop(e){this.player.pause(),this.player.src=null}set_volume(e){void 0!==e.volume_level&&(this.player.volume=e.volume_level)}mute(e){this.player.muted=Boolean(e.mute)}update(){this.conn&&this.conn.sendMessage({type:"browser_mod/update",deviceID:o,data:{browser:{},player:{volume:this.player.volume,muted:this.player.muted,src:this.player.src,state:this.player_state}}})}}}]); \ No newline at end of file +!function(e){var t={};function o(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,o),a.l=!0,a.exports}o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)o.d(n,a,function(t){return e[t]}.bind(null,a));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){"use strict";o.r(t);let n=function(){if(window.fully&&"function"==typeof fully.getDeviceId)return fully.getDeviceId();if(!localStorage["lovelace-player-device-id"]){const e=()=>Math.floor(1e5*(1+Math.random())).toString(16).substring(1);localStorage["lovelace-player-device-id"]=`${e()}${e()}-${e()}${e()}`}return localStorage["lovelace-player-device-id"]}();const a=Object.getPrototypeOf(customElements.get("home-assistant-main")),s=a.prototype.html,r=a.prototype.css;function l(e,t=!1){!function(e,t,o=null){if((e=new Event(e,{bubbles:!0,cancelable:!1,composed:!0})).detail=t||{},o)o.dispatchEvent(e);else{var n=document.querySelector("home-assistant");(n=(n=(n=(n=(n=(n=(n=(n=(n=(n=(n=n&&n.shadowRoot)&&n.querySelector("home-assistant-main"))&&n.shadowRoot)&&n.querySelector("app-drawer-layout partial-panel-resolver"))&&n.shadowRoot||n)&&n.querySelector("ha-panel-lovelace"))&&n.shadowRoot)&&n.querySelector("hui-root"))&&n.shadowRoot)&&n.querySelector("ha-app-layout #view"))&&n.firstElementChild)&&n.dispatchEvent(e)}}("hass-more-info",{entityId:e},document.querySelector("home-assistant"));const o=document.querySelector("home-assistant")._moreInfoEl;return o.large=t,o}customElements.define("browser-player",class extends a{static get properties(){return{hass:{}}}setConfig(e){this._config=e}handleMute(e){window.browser_mod.mute({})}handleVolumeChange(e){const t=parseFloat(e.target.value);window.browser_mod.set_volume({volume_level:t})}handleMoreInfo(e){l(window.browser_mod.entity_id)}handlePlayPause(e){window.browser_mod.player.paused?window.browser_mod.play({}):window.browser_mod.pause({})}render(){const e=window.browser_mod.player;return s` + + + + + + ${"stopped"===window.browser_mod.player_state?s``:s` + + `} + + + + + ${n} + + + + `}static get styles(){return r` + paper-icon-button[highlight] { + color: var(--accent-color); + } + .card-content { + display: flex; + justify-content: center; + } + .placeholder { + width: 24px; + padding: 8px; + } + .device-id { + opacity: 0.7; + font-size: xx-small; + margin-top: -10px; + user-select: all; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + } + `}});window.browser_mod=new class{constructor(){window.hassConnection.then(e=>this.connect(e.conn)),this.player=new Audio,this.player.addEventListener("ended",this.update.bind(this)),this.player.addEventListener("play",this.update.bind(this)),this.player.addEventListener("pause",this.update.bind(this)),this.player.addEventListener("volumechange",this.update.bind(this))}connect(e){console.log("Connection opened. Connecting to browser_mod"),this.conn=e,e.subscribeMessage(e=>this.callback(e),{type:"browser_mod/connect",deviceID:n}),console.log("Connected"),console.log(this.connection)}callback(e){switch(console.log("Got ws message"),console.log(e),e.command){case"update":this.update(e);break;case"play":this.play(e);break;case"pause":this.pause(e);break;case"stop":this.stop(e);break;case"set_volume":this.set_volume(e);break;case"mute":this.mute(e)}}get player_state(){return this.player.src?this.player.ended?"stopped":this.player.paused?"paused":"playing":"stopped"}play(e){const t=e.media_content_id;t&&(this.player.src=t),this.player.play()}pause(e){this.player.pause()}stop(e){this.player.pause(),this.player.src=null}set_volume(e){void 0!==e.volume_level&&(this.player.volume=e.volume_level)}mute(e){void 0===e.mute&&(e.mute=!this.player.muted),this.player.muted=Boolean(e.mute)}update(e=null){this.conn&&(e&&e.entity_id&&(this.entity_id=e.entity_id),this.conn.sendMessage({type:"browser_mod/update",deviceID:n,data:{browser:{},player:{volume:this.player.volume,muted:this.player.muted,src:this.player.src,state:this.player_state}}}))}}}]); \ No newline at end of file diff --git a/custom_components/browser_mod/connection.py b/custom_components/browser_mod/connection.py index c746ff7..966ec50 100644 --- a/custom_components/browser_mod/connection.py +++ b/custom_components/browser_mod/connection.py @@ -62,7 +62,7 @@ class BrowserModEntity(Entity): self._ws_cid = cid self._ws_connection = connection _LOGGER.error(f"Connecting {self.entity_id}") - self.ws_send("update") + self.ws_send("update", entity_id=self.entity_id) connection.subscriptions[cid] = self.ws_disconnect if self.hass: self.schedule_update_ha_state() diff --git a/js/browser-player.js b/js/browser-player.js new file mode 100644 index 0000000..6cc27e5 --- /dev/null +++ b/js/browser-player.js @@ -0,0 +1,107 @@ +import { LitElement, html, css } from "/card-tools/lit-element"; +import { deviceID } from "/card-tools/deviceId" +import { moreInfo } from "/card-tools/more-info" + +class BrowserPlayer extends LitElement { + + static get properties() { + return { + hass: {}, + }; + } + + setConfig(config) { + this._config = config; + } + handleMute(ev) { + window.browser_mod.mute({}); + } + handleVolumeChange(ev) { + const vol = parseFloat(ev.target.value); + window.browser_mod.set_volume({volume_level: vol}); + } + handleMoreInfo(ev) { + moreInfo(window.browser_mod.entity_id); + } + handlePlayPause(ev) { + if (window.browser_mod.player.paused) + window.browser_mod.play({}); + else + window.browser_mod.pause({}); + } + + render() { + const player = window.browser_mod.player; + return html` + + + + + + ${window.browser_mod.player_state === "stopped" + ? html`` + : html` + + `} + + + + + ${deviceID} + + + + `; + } + + static get styles() { + return css` + paper-icon-button[highlight] { + color: var(--accent-color); + } + .card-content { + display: flex; + justify-content: center; + } + .placeholder { + width: 24px; + padding: 8px; + } + .device-id { + opacity: 0.7; + font-size: xx-small; + margin-top: -10px; + user-select: all; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + } + ` + } + +} + +customElements.define("browser-player", BrowserPlayer); diff --git a/js/main.js b/js/main.js index 0f9a952..ec9bf23 100644 --- a/js/main.js +++ b/js/main.js @@ -1,4 +1,6 @@ import {deviceID} from "/card-tools/deviceId" +import "./browser-player" + class BrowserMod { constructor() { @@ -73,13 +75,19 @@ class BrowserMod { this.player.volume = msg.volume_level; } mute(msg) { + if (msg.mute === undefined) + msg.mute = !this.player.muted; this.player.muted = Boolean(msg.mute) } - update() { + update(msg=null) { if(!this.conn) return; + if(msg) + if(msg.entity_id) + this.entity_id = msg.entity_id; + this.conn.sendMessage({ type: 'browser_mod/update', deviceID: deviceID,