diff --git a/src/layouts/app/home-assistant.ts b/src/layouts/app/home-assistant.ts index e7141e3b46..62529ef38b 100644 --- a/src/layouts/app/home-assistant.ts +++ b/src/layouts/app/home-assistant.ts @@ -17,6 +17,8 @@ import { dialogManagerMixin } from "./dialog-manager-mixin"; import ConnectionMixin from "./connection-mixin"; import NotificationMixin from "./notification-mixin"; import DisconnectToastMixin from "./disconnect-toast-mixin"; +import { urlSyncMixin } from "./url-sync-mixin"; + import { Route, HomeAssistant } from "../../types"; import { navigate } from "../../common/navigate"; @@ -36,6 +38,7 @@ export class HomeAssistantAppEl extends ext(HassBaseMixin(LitElement), [ ConnectionMixin, NotificationMixin, dialogManagerMixin, + urlSyncMixin, ]) { @property() private _route?: Route; @property() private _error?: boolean; diff --git a/src/layouts/app/more-info-mixin.ts b/src/layouts/app/more-info-mixin.ts index c4a3d8fed5..66c442cf90 100644 --- a/src/layouts/app/more-info-mixin.ts +++ b/src/layouts/app/more-info-mixin.ts @@ -6,7 +6,7 @@ declare global { // for fire event interface HASSDomEvents { "hass-more-info": { - entityId: string; + entityId: string | null; }; } } diff --git a/src/layouts/app/url-sync-mixin.ts b/src/layouts/app/url-sync-mixin.ts new file mode 100644 index 0000000000..c6817760a6 --- /dev/null +++ b/src/layouts/app/url-sync-mixin.ts @@ -0,0 +1,90 @@ +import { Constructor, LitElement } from "lit-element"; +import { HassBaseEl } from "./hass-base-mixin"; +import { fireEvent } from "../../common/dom/fire_event"; + +/* tslint:disable:no-console */ +const DEBUG = false; + +export const urlSyncMixin = ( + superClass: Constructor +) => + // Disable this functionality in the demo. + __DEMO__ + ? superClass + : class extends superClass { + private _ignoreNextHassChange = false; + private _ignoreNextPopstate = false; + private _moreInfoOpenedFromPath?: string; + + public connectedCallback(): void { + super.connectedCallback(); + window.addEventListener("popstate", this._popstateChangeListener); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + window.removeEventListener("popstate", this._popstateChangeListener); + } + + protected hassChanged(newHass, oldHass): void { + super.hassChanged(newHass, oldHass); + + if (this._ignoreNextHassChange) { + if (DEBUG) { + console.log("ignore hasschange"); + } + this._ignoreNextHassChange = false; + return; + } + if ( + !oldHass || + oldHass.moreInfoEntityId === newHass.moreInfoEntityId + ) { + if (DEBUG) { + console.log("ignoring hass change"); + } + return; + } + + if (newHass.moreInfoEntityId) { + if (DEBUG) { + console.log("pushing state"); + } + // We keep track of where we opened moreInfo from so that we don't + // pop the state when we close the modal if the modal has navigated + // us away. + this._moreInfoOpenedFromPath = window.location.pathname; + history.pushState(null, "", window.location.pathname); + } else if ( + window.location.pathname === this._moreInfoOpenedFromPath + ) { + if (DEBUG) { + console.log("history back"); + } + this._ignoreNextPopstate = true; + history.back(); + } + } + + private _popstateChangeListener = (ev) => { + if (this._ignoreNextPopstate) { + if (DEBUG) { + console.log("ignore popstate"); + } + this._ignoreNextPopstate = false; + return; + } + + if (DEBUG) { + console.log("popstate", ev); + } + + if (this.hass && this.hass.moreInfoEntityId) { + if (DEBUG) { + console.log("deselect entity"); + } + this._ignoreNextHassChange = true; + fireEvent(this, "hass-more-info", { entityId: null }); + } + }; + }; diff --git a/src/layouts/home-assistant-main.ts b/src/layouts/home-assistant-main.ts index 58679ff86a..656064920f 100644 --- a/src/layouts/home-assistant-main.ts +++ b/src/layouts/home-assistant-main.ts @@ -15,8 +15,6 @@ import { AppDrawerElement } from "@polymer/app-layout/app-drawer/app-drawer"; import "@polymer/app-route/app-route"; import "@polymer/iron-media-query/iron-media-query"; -import "../util/ha-url-sync"; - import "./partial-panel-resolver"; import { HomeAssistant, Route } from "../types"; import { fireEvent } from "../common/dom/fire_event"; @@ -47,7 +45,6 @@ class HomeAssistantMain extends LitElement { const disableSwipe = NON_SWIPABLE_PANELS.indexOf(hass.panelUrl) !== -1; return html` -