diff --git a/README.md b/README.md index 349a33c..86eb15f 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,16 @@ service_data: Remove a blackout. +### lovelace-reload +``` +service: browser_mod.command +service_data: + command: lovelace-reload +``` + +Refreshes the lovelace config. Same as clicking "Refresh" in the top right menu in lovelace. + + ## `browser-player` card To control the playback in the current *device*, `browser_mod` includes a custom lovelace card. Just add diff --git a/custom_components/browser_mod/browser_mod.js b/custom_components/browser_mod/browser_mod.js index 5f03c46..9b836ba 100644 --- a/custom_components/browser_mod/browser_mod.js +++ b/custom_components/browser_mod/browser_mod.js @@ -1,4 +1,4 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var s=t[o]={i:o,l:!1,exports:{}};return e[o].call(s.exports,s,s.exports,n),s.l=!0,s.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 s in e)n.d(o,s,function(t){return e[t]}.bind(null,s));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"]}();function s(e){return document.querySelector("home-assistant").provideHass(e)}function i(e,t,n=null){if((e=new Event(e,{bubbles:!0,cancelable:!1,composed:!0})).detail=t||{},n)n.dispatchEvent(e);else{var o=document.querySelector("home-assistant");(o=(o=(o=(o=(o=(o=(o=(o=(o=(o=(o=o&&o.shadowRoot)&&o.querySelector("home-assistant-main"))&&o.shadowRoot)&&o.querySelector("app-drawer-layout partial-panel-resolver"))&&o.shadowRoot||o)&&o.querySelector("ha-panel-lovelace"))&&o.shadowRoot)&&o.querySelector("hui-root"))&&o.shadowRoot)&&o.querySelector("ha-app-layout #view"))&&o.firstElementChild)&&o.dispatchEvent(e)}}const a="custom:";function r(e,t){const n=document.createElement("hui-error-card");return n.setConfig({type:"error",error:e,config:t}),n}function l(e,t){if(!t||"object"!=typeof t||!t.type)return r(`No ${e} type configured`,t);let n=t.type;if(n=n.startsWith(a)?n.substr(a.length):`hui-${n}-${e}`,customElements.get(n))return function(e,t){const n=document.createElement(e);try{n.setConfig(t)}catch(e){return r(e,t)}return n}(n,t);const o=r(`Custom element doesn't exist: ${n}.`,t);o.style.display="None";const s=setTimeout(()=>{o.style.display=""},2e3);return customElements.whenDefined(n).then(()=>{clearTimeout(s),i("ll-rebuild",{},o)}),o}function c(e,t=!1){i("hass-more-info",{entityId:e},document.querySelector("home-assistant"));const n=document.querySelector("home-assistant")._moreInfoEl;return n.large=t,n}const d=Object.getPrototypeOf(customElements.get("home-assistant-main")),u=d.prototype.html,p=d.prototype.css;class h extends d{static get properties(){return{hass:{},config:{}}}setConfig(e){this._config=e,this.el?this.el.setConfig(e):this.el=this.create(e),this._hass&&(this.el.hass=this._hass),this.noHass&&s(this)}set config(e){this.setConfig(e)}set hass(e){this._hass=e,this.el&&(this.el.hass=e)}createRenderRoot(){return this}render(){return u`${this.el}`}}if(!customElements.get("card-maker")){class e extends h{create(e){return function(e){return l("card",e)}(e)}}customElements.define("card-maker",e)}if(!customElements.get("element-maker")){class e extends h{create(e){return function(e){return l("element",e)}(e)}}customElements.define("element-maker",e)}if(!customElements.get("entity-row-maker")){class e extends h{create(e){return function(e){const t=new Set(["call-service","divider","section","weblink"]);if(!e)return r("Invalid configuration given.",e);if("string"==typeof e&&(e={entity:e}),"object"!=typeof e||!e.entity&&!e.type)return r("Invalid configuration given.",e);const n=e.type||"default";if(t.has(n)||n.startsWith(a))return l("row",e);const o=e.entity.split(".",1)[0];return Object.assign(e,{type:{alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"}[o]||"text"}),l("entity-row",e)}(e)}}customElements.define("entity-row-maker",e)}function m(e,t,n=!1,o=null){c(Object.keys(document.querySelector("home-assistant").hass.states)[0]);const s=document.createElement("card-maker");s.noHass=!0,s.config=t;const i=document.createElement("div");i.innerHTML=`\n \n \n \n
\n ${e}\n
\n
\n `,i.appendChild(s);const a=document.querySelector("home-assistant")._moreInfoEl;a.large=n,a._page="none",a.shadowRoot.appendChild(i);let r={};if(o)for(var l in o)r[l]=a.style[l],a.style.setProperty(l,o[l]);return setTimeout(()=>{let e=setInterval(()=>{if(a.getAttribute("aria-hidden"))for(var t in clearInterval(e),i.parentNode.removeChild(i),r)a.style.setProperty(t,r[t])},100)},1e3),a}customElements.define("browser-player",class extends d{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){c(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 u` +!function(e){var t={};function o(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,o),s.l=!0,s.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 s in e)o.d(n,s,function(t){return e[t]}.bind(null,s));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"]}();function s(e){return document.querySelector("home-assistant").provideHass(e)}function i(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)}}const a="custom:";function r(e,t){const o=document.createElement("hui-error-card");return o.setConfig({type:"error",error:e,config:t}),o}function l(e,t){if(!t||"object"!=typeof t||!t.type)return r(`No ${e} type configured`,t);let o=t.type;if(o=o.startsWith(a)?o.substr(a.length):`hui-${o}-${e}`,customElements.get(o))return function(e,t){const o=document.createElement(e);try{o.setConfig(t)}catch(e){return r(e,t)}return o}(o,t);const n=r(`Custom element doesn't exist: ${o}.`,t);n.style.display="None";const s=setTimeout(()=>{n.style.display=""},2e3);return customElements.whenDefined(o).then(()=>{clearTimeout(s),i("ll-rebuild",{},n)}),n}function c(e,t=!1){i("hass-more-info",{entityId:e},document.querySelector("home-assistant"));const o=document.querySelector("home-assistant")._moreInfoEl;return o.large=t,o}const d=Object.getPrototypeOf(customElements.get("home-assistant-main")),u=d.prototype.html,h=d.prototype.css;class p extends d{static get properties(){return{hass:{},config:{}}}setConfig(e){this._config=e,this.el?this.el.setConfig(e):this.el=this.create(e),this._hass&&(this.el.hass=this._hass),this.noHass&&s(this)}set config(e){this.setConfig(e)}set hass(e){this._hass=e,this.el&&(this.el.hass=e)}createRenderRoot(){return this}render(){return u`${this.el}`}}if(!customElements.get("card-maker")){class e extends p{create(e){return function(e){return l("card",e)}(e)}}customElements.define("card-maker",e)}if(!customElements.get("element-maker")){class e extends p{create(e){return function(e){return l("element",e)}(e)}}customElements.define("element-maker",e)}if(!customElements.get("entity-row-maker")){class e extends p{create(e){return function(e){const t=new Set(["call-service","divider","section","weblink"]);if(!e)return r("Invalid configuration given.",e);if("string"==typeof e&&(e={entity:e}),"object"!=typeof e||!e.entity&&!e.type)return r("Invalid configuration given.",e);const o=e.type||"default";if(t.has(o)||o.startsWith(a))return l("row",e);const n=e.entity.split(".",1)[0];return Object.assign(e,{type:{alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"}[n]||"text"}),l("entity-row",e)}(e)}}customElements.define("entity-row-maker",e)}function m(e,t,o=!1,n=null){c(Object.keys(document.querySelector("home-assistant").hass.states)[0]);const s=document.createElement("card-maker");s.noHass=!0,s.config=t;const i=document.createElement("div");i.innerHTML=`\n \n \n \n
\n ${e}\n
\n
\n `,i.appendChild(s);const a=document.querySelector("home-assistant")._moreInfoEl;a.large=o,a._page="none",a.shadowRoot.appendChild(i);let r={};if(n)for(var l in n)r[l]=a.style[l],a.style.setProperty(l,n[l]);return setTimeout(()=>{let e=setInterval(()=>{if(a.getAttribute("aria-hidden"))for(var t in clearInterval(e),i.parentNode.removeChild(i),r)a.style.setProperty(t,r[t])},100)},1e3),a}customElements.define("browser-player",class extends d{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){c(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 u`
- ${o} + ${n}
- `}static get styles(){return p` + `}static get styles(){return h` paper-icon-button[highlight] { color: var(--accent-color); } @@ -53,4 +53,4 @@ -moz-user-select: all; -ms-user-select: all; } - `}});window.browser_mod=new class{set hass(e){if(!e)return;if(this._hass=e,this.hassPatched)return;const t=e.callService;e.callService=(e,n,s)=>{if("browser_mod"===e&&"command"===n&&s.deviceID){const e=s.deviceID.indexOf("this");-1!==e&&(s.deviceID[e]=o)}t(e,n,s)},this.hassPatched=!0,document.querySelector("home-assistant").hassChanged(e,e)}playOnce(e){window.browser_mod.playedOnce||(window.browser_mod.player.play(),window.browser_mod.playedOnce=!0)}constructor(){window.hassConnection.then(e=>this.connect(e.conn)),this.player=new Audio,this.playedOnce=!1;const e=this.update.bind(this);this.player.addEventListener("ended",e),this.player.addEventListener("play",e),this.player.addEventListener("pause",e),this.player.addEventListener("volumechange",e),document.addEventListener("visibilitychange",e),window.addEventListener("location-changed",e),window.addEventListener("click",this.playOnce),window.addEventListener("mousemove",this.no_blackout.bind(this)),window.addEventListener("mousedown",this.no_blackout.bind(this)),window.addEventListener("keydown",this.no_blackout.bind(this)),window.addEventListener("touchstart",this.no_blackout.bind(this)),s(this),this._blackout=document.createElement("div"),this._blackout.style.cssText="\n position: fixed;\n left: 0;\n top: 0;\n padding: 0;\n margin: 0;\n width: 100%;\n height: 100%;\n background: black;\n visibility: hidden;\n ",document.body.appendChild(this._blackout)}connect(e){this.conn=e,e.subscribeMessage(e=>this.callback(e),{type:"browser_mod/connect",deviceID:o})}callback(e){switch(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);break;case"popup":this.popup(e);break;case"close-popup":this.close_popup(e);break;case"navigate":this.navigate(e);break;case"more-info":this.more_info(e);break;case"set-theme":this.set_theme(e);break;case"blackout":this.blackout(e);break;case"no-blackout":this.no_blackout(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)}popup(e){e.title&&e.card&&m(e.title,e.card,e.large,e.style)}close_popup(e){document.querySelector("home-assistant")._moreInfoEl.close()}navigate(e){e.navigation_path&&(history.pushState(null,"",e.navigation_path),i("location-changed",{},document.querySelector("home-assistant")))}more_info(e){e.entity_id&&c(e.entity_id,e.large)}set_theme(e){e.theme||(e.theme="default"),i("settheme",e.theme,document.querySelector("home-assistant"))}blackout(e){this._blackout.style.visibility="visible",this.update()}no_blackout(e){this._blackout.style.visibility="hidden",this.update()}update(e=null){this.conn&&(e&&e.entity_id&&(this.entity_id=e.entity_id),this.conn.sendMessage({type:"browser_mod/update",deviceID:o,data:{browser:{path:window.location.pathname,visibility:document.visibilityState,userAgent:navigator.userAgent,currentUser:this._hass&&this._hass.user&&this._hass.user.name,blackout:Boolean("visible"===this._blackout.style.visibility)},player:{volume:this.player.volume,muted:this.player.muted,src:this.player.src,state:this.player_state}}}))}}}]); \ No newline at end of file + `}});window.browser_mod=new class{set hass(e){if(!e)return;if(this._hass=e,this.hassPatched)return;const t=e.callService;e.callService=(e,o,s)=>{if("browser_mod"===e&&"command"===o&&s.deviceID){const e=s.deviceID.indexOf("this");-1!==e&&(s.deviceID[e]=n)}t(e,o,s)},this.hassPatched=!0,document.querySelector("home-assistant").hassChanged(e,e)}playOnce(e){window.browser_mod.playedOnce||(window.browser_mod.player.play(),window.browser_mod.playedOnce=!0)}constructor(){window.hassConnection.then(e=>this.connect(e.conn)),this.player=new Audio,this.playedOnce=!1;const e=this.update.bind(this);this.player.addEventListener("ended",e),this.player.addEventListener("play",e),this.player.addEventListener("pause",e),this.player.addEventListener("volumechange",e),document.addEventListener("visibilitychange",e),window.addEventListener("location-changed",e),window.addEventListener("click",this.playOnce),window.addEventListener("mousemove",this.no_blackout.bind(this)),window.addEventListener("mousedown",this.no_blackout.bind(this)),window.addEventListener("keydown",this.no_blackout.bind(this)),window.addEventListener("touchstart",this.no_blackout.bind(this)),s(this),this._blackout=document.createElement("div"),this._blackout.style.cssText="\n position: fixed;\n left: 0;\n top: 0;\n padding: 0;\n margin: 0;\n width: 100%;\n height: 100%;\n background: black;\n visibility: hidden;\n ",document.body.appendChild(this._blackout)}connect(e){this.conn=e,e.subscribeMessage(e=>this.callback(e),{type:"browser_mod/connect",deviceID:n})}callback(e){switch(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);break;case"popup":this.popup(e);break;case"close-popup":this.close_popup(e);break;case"navigate":this.navigate(e);break;case"more-info":this.more_info(e);break;case"set-theme":this.set_theme(e);break;case"lovelace-reload":this.lovelace_reload(e);break;case"blackout":this.blackout(e);break;case"no-blackout":this.no_blackout(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)}popup(e){e.title&&e.card&&m(e.title,e.card,e.large,e.style)}close_popup(e){document.querySelector("home-assistant")._moreInfoEl.close()}navigate(e){e.navigation_path&&(history.pushState(null,"",e.navigation_path),i("location-changed",{},document.querySelector("home-assistant")))}more_info(e){e.entity_id&&c(e.entity_id,e.large)}set_theme(e){e.theme||(e.theme="default"),i("settheme",e.theme,document.querySelector("home-assistant"))}lovelace_reload(e){const t=o=(o=(o=(o=(o=(o=(o=(o=(o=(o=(o=(o=document.querySelector("home-assistant"))&&o.shadowRoot)&&o.querySelector("home-assistant-main"))&&o.shadowRoot)&&o.querySelector("app-drawer-layout partial-panel-resolver"))&&o.shadowRoot||o)&&o.querySelector("ha-panel-lovelace"))&&o.shadowRoot)&&o.querySelector("hui-root"))&&o.shadowRoot)&&o.querySelector("ha-app-layout #view"))&&o.firstElementChild;var o;t&&i("config-refresh",{},t)}blackout(e){this._blackout.style.visibility="visible",this.update()}no_blackout(e){this._blackout.style.visibility="hidden",this.update()}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:{path:window.location.pathname,visibility:document.visibilityState,userAgent:navigator.userAgent,currentUser:this._hass&&this._hass.user&&this._hass.user.name,blackout:Boolean("visible"===this._blackout.style.visibility)},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/js/main.js b/js/main.js index 06a1d18..edd230c 100644 --- a/js/main.js +++ b/js/main.js @@ -1,5 +1,5 @@ import { deviceID } from "/card-tools/deviceId"; -import { provideHass } from "/card-tools/hass"; +import { lovelace_view, provideHass } from "/card-tools/hass"; import { popUp, closePopUp } from "/card-tools/popup"; import { fireEvent } from "/card-tools/event"; import { moreInfo } from "/card-tools/more-info.js"; @@ -114,6 +114,10 @@ class BrowserMod { this.set_theme(msg); break; + case "lovelace-reload": + this.lovelace_reload(msg); + break; + case "blackout": this.blackout(msg); break; @@ -175,6 +179,12 @@ class BrowserMod { fireEvent("settheme", msg.theme, document.querySelector("home-assistant")); } + lovelace_reload(msg) { + const ll = lovelace_view(); + if (ll) + fireEvent("config-refresh", {}, ll); + } + blackout(msg){ this._blackout.style.visibility = "visible"; this.update();