mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Close dialogs on history back (#6354)
This commit is contained in:
parent
3bc54aa9e0
commit
3d32e6310d
@ -35,6 +35,7 @@ import "./step-flow-external";
|
||||
import "./step-flow-form";
|
||||
import "./step-flow-loading";
|
||||
import "./step-flow-pick-handler";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
|
||||
let instance = 0;
|
||||
@ -114,6 +115,17 @@ class DataEntryFlowDialog extends LitElement {
|
||||
this._loading = false;
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
if (this._step) {
|
||||
this._flowDone();
|
||||
} else if (this._step === null) {
|
||||
// Flow aborted during picking flow
|
||||
this._step = undefined;
|
||||
this._params = undefined;
|
||||
}
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._params) {
|
||||
return html``;
|
||||
@ -122,7 +134,7 @@ class DataEntryFlowDialog extends LitElement {
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@closing=${this._close}
|
||||
@closed=${this.closeDialog}
|
||||
scrimClickAction
|
||||
escapeKeyAction
|
||||
hideActions
|
||||
@ -297,16 +309,6 @@ class DataEntryFlowDialog extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _close(): void {
|
||||
if (this._step) {
|
||||
this._flowDone();
|
||||
} else if (this._step === null) {
|
||||
// Flow aborted during picking flow
|
||||
this._step = undefined;
|
||||
this._params = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyleDialog,
|
||||
|
@ -16,6 +16,7 @@ import { PolymerChangedEvent } from "../../polymer-types";
|
||||
import { haStyleDialog } from "../../resources/styles";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { DialogParams } from "./show-dialog-box";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
|
||||
@customElement("dialog-box")
|
||||
class DialogBox extends LitElement {
|
||||
@ -32,6 +33,17 @@ class DialogBox extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
public closeDialog(): boolean {
|
||||
if (this._params?.confirmation || this._params?.prompt) {
|
||||
this._dismiss();
|
||||
return true;
|
||||
}
|
||||
if (this._params) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._params) {
|
||||
return html``;
|
||||
@ -100,11 +112,11 @@ class DialogBox extends LitElement {
|
||||
this._value = ev.detail.value;
|
||||
}
|
||||
|
||||
private async _dismiss(): Promise<void> {
|
||||
private _dismiss(): void {
|
||||
if (this._params!.cancel) {
|
||||
this._params!.cancel();
|
||||
}
|
||||
this._params = undefined;
|
||||
this._close();
|
||||
}
|
||||
|
||||
private _handleKeyUp(ev: KeyboardEvent) {
|
||||
@ -113,15 +125,16 @@ class DialogBox extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private async _confirm(): Promise<void> {
|
||||
private _confirm(): void {
|
||||
if (this._params!.confirm) {
|
||||
this._params!.confirm(this._value);
|
||||
}
|
||||
this._dismiss();
|
||||
this._close();
|
||||
}
|
||||
|
||||
private _close(): void {
|
||||
this._params = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
|
@ -6,15 +6,18 @@ declare global {
|
||||
interface HASSDomEvents {
|
||||
"show-dialog": ShowDialogParams<unknown>;
|
||||
"close-dialog": undefined;
|
||||
"dialog-closed": DialogClosedParams;
|
||||
}
|
||||
// for add event listener
|
||||
interface HTMLElementEventMap {
|
||||
"show-dialog": HASSDomEvent<ShowDialogParams<unknown>>;
|
||||
"dialog-closed": HASSDomEvent<DialogClosedParams>;
|
||||
}
|
||||
}
|
||||
|
||||
interface HassDialog<T = HASSDomEvents[ValidHassDomEvent]> extends HTMLElement {
|
||||
showDialog(params: T);
|
||||
closeDialog?: () => boolean | void;
|
||||
}
|
||||
|
||||
interface ShowDialogParams<T> {
|
||||
@ -23,16 +26,30 @@ interface ShowDialogParams<T> {
|
||||
dialogParams: T;
|
||||
}
|
||||
|
||||
export interface DialogClosedParams {
|
||||
dialog: string;
|
||||
}
|
||||
|
||||
export interface DialogState {
|
||||
dialog: string;
|
||||
open: boolean;
|
||||
oldState: null | DialogState;
|
||||
dialogParams?: unknown;
|
||||
}
|
||||
|
||||
const LOADED = {};
|
||||
|
||||
export const showDialog = async (
|
||||
element: HTMLElement & ProvideHassElement,
|
||||
root: ShadowRoot | HTMLElement,
|
||||
dialogImport: () => Promise<unknown>,
|
||||
dialogTag: string,
|
||||
dialogParams: unknown
|
||||
dialogParams: unknown,
|
||||
dialogImport?: () => Promise<unknown>
|
||||
) => {
|
||||
if (!(dialogTag in LOADED)) {
|
||||
if (!dialogImport) {
|
||||
return;
|
||||
}
|
||||
LOADED[dialogTag] = dialogImport().then(() => {
|
||||
const dialogEl = document.createElement(dialogTag) as HassDialog;
|
||||
element.provideHass(dialogEl);
|
||||
@ -40,19 +57,55 @@ export const showDialog = async (
|
||||
return dialogEl;
|
||||
});
|
||||
}
|
||||
|
||||
history.replaceState(
|
||||
{
|
||||
dialog: dialogTag,
|
||||
open: false,
|
||||
oldState:
|
||||
history.state?.open && history.state?.dialog !== dialogTag
|
||||
? history.state
|
||||
: null,
|
||||
},
|
||||
""
|
||||
);
|
||||
try {
|
||||
history.pushState(
|
||||
{ dialog: dialogTag, dialogParams: dialogParams, open: true },
|
||||
""
|
||||
);
|
||||
} catch (err) {
|
||||
// dialogParams could not be cloned, probably contains callback
|
||||
history.pushState(
|
||||
{ dialog: dialogTag, dialogParams: null, open: true },
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
const dialogElement = await LOADED[dialogTag];
|
||||
dialogElement.showDialog(dialogParams);
|
||||
};
|
||||
|
||||
export const closeDialog = async (dialogTag: string): Promise<boolean> => {
|
||||
if (!(dialogTag in LOADED)) {
|
||||
return true;
|
||||
}
|
||||
const dialogElement = await LOADED[dialogTag];
|
||||
if (dialogElement.closeDialog) {
|
||||
return dialogElement.closeDialog() !== false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const makeDialogManager = (
|
||||
element: HTMLElement & ProvideHassElement,
|
||||
root: ShadowRoot | HTMLElement
|
||||
) => {
|
||||
element.addEventListener(
|
||||
"show-dialog",
|
||||
async (e: HASSDomEvent<ShowDialogParams<unknown>>) => {
|
||||
(e: HASSDomEvent<ShowDialogParams<unknown>>) => {
|
||||
const { dialogTag, dialogImport, dialogParams } = e.detail;
|
||||
showDialog(element, root, dialogImport, dialogTag, dialogParams);
|
||||
showDialog(element, root, dialogTag, dialogParams, dialogImport);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { DOMAINS_MORE_INFO_NO_HISTORY } from "../../common/const";
|
||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||
import { navigate } from "../../common/navigate";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import "../../components/state-history-charts";
|
||||
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { showEntityEditorDialog } from "../../panels/config/entities/show-dialog-entity-editor";
|
||||
@ -24,7 +25,6 @@ import {
|
||||
} from "lit-element";
|
||||
import { haStyleDialog } from "../../resources/styles";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { getRecentWithCache } from "../../data/cached-history";
|
||||
import { computeDomain } from "../../common/entity/compute_domain";
|
||||
import { mdiClose, mdiCog, mdiPencil } from "@mdi/js";
|
||||
@ -34,6 +34,10 @@ const DOMAINS_NO_INFO = ["camera", "configurator", "history_graph"];
|
||||
const EDITABLE_DOMAINS_WITH_ID = ["scene", "automation"];
|
||||
const EDITABLE_DOMAINS = ["script"];
|
||||
|
||||
export interface MoreInfoDialogParams {
|
||||
entityId: string | null;
|
||||
}
|
||||
|
||||
@customElement("ha-more-info-dialog")
|
||||
export class MoreInfoDialog extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@ -42,39 +46,39 @@ export class MoreInfoDialog extends LitElement {
|
||||
|
||||
@internalProperty() private _stateHistory?: HistoryResult;
|
||||
|
||||
@internalProperty() private _entityId?: string | null;
|
||||
|
||||
private _historyRefreshInterval?: number;
|
||||
|
||||
protected updated(changedProperties) {
|
||||
super.updated(changedProperties);
|
||||
if (!changedProperties.has("hass")) {
|
||||
return;
|
||||
public showDialog(params: MoreInfoDialogParams) {
|
||||
this._entityId = params.entityId;
|
||||
if (!this._entityId) {
|
||||
this.closeDialog();
|
||||
}
|
||||
const oldHass = changedProperties.get("hass");
|
||||
if (oldHass && oldHass.moreInfoEntityId === this.hass.moreInfoEntityId) {
|
||||
return;
|
||||
}
|
||||
if (this.hass.moreInfoEntityId) {
|
||||
this.large = false;
|
||||
this._stateHistory = undefined;
|
||||
if (this._computeShowHistoryComponent(this.hass.moreInfoEntityId)) {
|
||||
this._getStateHistory();
|
||||
clearInterval(this._historyRefreshInterval);
|
||||
this._historyRefreshInterval = window.setInterval(() => {
|
||||
this._getStateHistory();
|
||||
}, 60 * 1000);
|
||||
}
|
||||
} else {
|
||||
this._stateHistory = undefined;
|
||||
this.large = false;
|
||||
this._stateHistory = undefined;
|
||||
if (this._computeShowHistoryComponent(this._entityId)) {
|
||||
this._getStateHistory();
|
||||
clearInterval(this._historyRefreshInterval);
|
||||
this._historyRefreshInterval = undefined;
|
||||
this._historyRefreshInterval = window.setInterval(() => {
|
||||
this._getStateHistory();
|
||||
}, 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
this._entityId = undefined;
|
||||
this._stateHistory = undefined;
|
||||
clearInterval(this._historyRefreshInterval);
|
||||
this._historyRefreshInterval = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass.moreInfoEntityId) {
|
||||
if (!this._entityId) {
|
||||
return html``;
|
||||
}
|
||||
const entityId = this.hass.moreInfoEntityId;
|
||||
const entityId = this._entityId;
|
||||
const stateObj = this.hass.states[entityId];
|
||||
const domain = computeDomain(entityId);
|
||||
|
||||
@ -85,7 +89,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@closed=${this._close}
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${true}
|
||||
hideActions
|
||||
data-domain=${domain}
|
||||
@ -174,15 +178,15 @@ export class MoreInfoDialog extends LitElement {
|
||||
}
|
||||
|
||||
private async _getStateHistory(): Promise<void> {
|
||||
if (!this.hass.moreInfoEntityId) {
|
||||
if (!this._entityId) {
|
||||
return;
|
||||
}
|
||||
this._stateHistory = await getRecentWithCache(
|
||||
this.hass!,
|
||||
this.hass.moreInfoEntityId,
|
||||
this._entityId,
|
||||
{
|
||||
refresh: 60,
|
||||
cacheKey: `more_info.${this.hass.moreInfoEntityId}`,
|
||||
cacheKey: `more_info.${this._entityId}`,
|
||||
hoursToShow: 24,
|
||||
},
|
||||
this.hass!.localize,
|
||||
@ -198,7 +202,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
}
|
||||
|
||||
private _removeEntity() {
|
||||
const entityId = this.hass.moreInfoEntityId!;
|
||||
const entityId = this._entityId!;
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.dialogs.more_info_control.restored.confirm_remove_title"
|
||||
@ -216,14 +220,14 @@ export class MoreInfoDialog extends LitElement {
|
||||
|
||||
private _gotoSettings() {
|
||||
showEntityEditorDialog(this, {
|
||||
entity_id: this.hass.moreInfoEntityId!,
|
||||
entity_id: this._entityId!,
|
||||
});
|
||||
fireEvent(this, "hass-more-info", { entityId: null });
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private _gotoEdit() {
|
||||
const stateObj = this.hass.states[this.hass.moreInfoEntityId!];
|
||||
const domain = computeDomain(this.hass.moreInfoEntityId!);
|
||||
const stateObj = this.hass.states[this._entityId!];
|
||||
const domain = computeDomain(this._entityId!);
|
||||
navigate(
|
||||
this,
|
||||
`/config/${domain}/edit/${
|
||||
@ -232,11 +236,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
: stateObj.entity_id
|
||||
}`
|
||||
);
|
||||
this._close();
|
||||
}
|
||||
|
||||
private _close() {
|
||||
fireEvent(this, "hass-more-info", { entityId: null });
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
@ -274,7 +274,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
--mdc-dialog-max-width: 90vw;
|
||||
}
|
||||
|
||||
app-toolbar {
|
||||
ha-dialog:not([data-domain="camera"]) app-toolbar {
|
||||
max-width: 368px;
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,8 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { cache } from "lit-html/directives/cache";
|
||||
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/ha-dialog";
|
||||
import "../../../components/ha-svg-icon";
|
||||
@ -72,6 +72,7 @@ export class DialogEntityEditor extends LitElement {
|
||||
|
||||
public closeDialog(): void {
|
||||
this._params = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
@ -20,6 +20,7 @@ import { haStyleDialog } from "../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
|
||||
import { formatSystemLogTime } from "./util";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
|
||||
class DialogSystemLogDetail extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@ -34,6 +35,11 @@ class DialogSystemLogDetail extends LitElement {
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
this._params = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
if (!changedProps.has("_params") || !this._params) {
|
||||
@ -137,7 +143,7 @@ class DialogSystemLogDetail extends LitElement {
|
||||
|
||||
private _openedChanged(ev: PolymerChangedEvent<boolean>): void {
|
||||
if (!(ev.detail as any).value) {
|
||||
this._params = undefined;
|
||||
this.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { addDistanceToCoord } from "../../../common/location/add_distance_to_coord";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
import "../../../components/ha-switch";
|
||||
@ -45,7 +46,7 @@ class DialogZoneDetail extends LitElement {
|
||||
|
||||
@property() private _submitting = false;
|
||||
|
||||
public async showDialog(params: ZoneDetailDialogParams): Promise<void> {
|
||||
public showDialog(params: ZoneDetailDialogParams): void {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
if (this._params.entry) {
|
||||
@ -74,7 +75,11 @@ class DialogZoneDetail extends LitElement {
|
||||
this._passive = false;
|
||||
this._radius = 100;
|
||||
}
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._params = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@ -93,7 +98,7 @@ class DialogZoneDetail extends LitElement {
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@closing="${this._close}"
|
||||
@closed="${this.closeDialog}"
|
||||
scrimClickAction=""
|
||||
escapeKeyAction=""
|
||||
.heading=${createCloseHeading(
|
||||
@ -276,10 +281,6 @@ class DialogZoneDetail extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _close(): void {
|
||||
this._params = undefined;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyleDialog,
|
||||
|
@ -2,6 +2,7 @@ import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
import { makeDialogManager, showDialog } from "../dialogs/make-dialog-manager";
|
||||
import { Constructor } from "../types";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { PropertyValues } from "lit-element";
|
||||
|
||||
interface RegisterDialogParams {
|
||||
dialogShowEvent: keyof HASSDomEvents;
|
||||
@ -24,7 +25,7 @@ export const dialogManagerMixin = <T extends Constructor<HassBaseEl>>(
|
||||
superClass: T
|
||||
) =>
|
||||
class extends superClass {
|
||||
protected firstUpdated(changedProps) {
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
// deprecated
|
||||
this.addEventListener("register-dialog", (e) =>
|
||||
@ -42,9 +43,9 @@ export const dialogManagerMixin = <T extends Constructor<HassBaseEl>>(
|
||||
showDialog(
|
||||
this,
|
||||
this.shadowRoot!,
|
||||
dialogImport,
|
||||
dialogTag,
|
||||
(showEv as HASSDomEvent<unknown>).detail
|
||||
(showEv as HASSDomEvent<unknown>).detail,
|
||||
dialogImport
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -1,35 +1,46 @@
|
||||
import { Constructor } from "../types";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { showDialog } from "../dialogs/make-dialog-manager";
|
||||
import type { Constructor } from "../types";
|
||||
import type { HassBaseEl } from "./hass-base-mixin";
|
||||
import type { MoreInfoDialogParams } from "../dialogs/more-info/ha-more-info-dialog";
|
||||
import type { PropertyValues } from "lit-element";
|
||||
import type { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
interface HASSDomEvents {
|
||||
"hass-more-info": {
|
||||
entityId: string | null;
|
||||
};
|
||||
"hass-more-info": MoreInfoDialogParams;
|
||||
}
|
||||
}
|
||||
|
||||
let moreInfoImportPromise;
|
||||
const importMoreInfo = () => {
|
||||
if (!moreInfoImportPromise) {
|
||||
moreInfoImportPromise = import(
|
||||
/* webpackChunkName: "more-info-dialog" */ "../dialogs/more-info/ha-more-info-dialog"
|
||||
);
|
||||
}
|
||||
return moreInfoImportPromise;
|
||||
};
|
||||
|
||||
export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
class extends superClass {
|
||||
private _moreInfoEl?: any;
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
this.addEventListener("hass-more-info", (e) => this._handleMoreInfo(e));
|
||||
this.addEventListener("hass-more-info", (ev) => this._handleMoreInfo(ev));
|
||||
|
||||
// Load it once we are having the initial rendering done.
|
||||
import(
|
||||
/* webpackChunkName: "more-info-dialog" */ "../dialogs/more-info/ha-more-info-dialog"
|
||||
);
|
||||
importMoreInfo();
|
||||
}
|
||||
|
||||
private async _handleMoreInfo(ev) {
|
||||
if (!this._moreInfoEl) {
|
||||
this._moreInfoEl = document.createElement("ha-more-info-dialog");
|
||||
this.shadowRoot!.appendChild(this._moreInfoEl);
|
||||
this.provideHass(this._moreInfoEl);
|
||||
}
|
||||
this._updateHass({ moreInfoEntityId: ev.detail.entityId });
|
||||
private async _handleMoreInfo(ev: HASSDomEvent<MoreInfoDialogParams>) {
|
||||
showDialog(
|
||||
this,
|
||||
this.shadowRoot!,
|
||||
"ha-more-info-dialog",
|
||||
{
|
||||
entityId: ev.detail.entityId,
|
||||
},
|
||||
importMoreInfo
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,15 @@
|
||||
/* eslint-disable no-console */
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import {
|
||||
closeDialog,
|
||||
showDialog,
|
||||
DialogState,
|
||||
DialogClosedParams,
|
||||
} from "../dialogs/make-dialog-manager";
|
||||
import { Constructor } from "../types";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
const DEBUG = false;
|
||||
const DEBUG = true;
|
||||
|
||||
export const urlSyncMixin = <T extends Constructor<HassBaseEl>>(
|
||||
superClass: T
|
||||
@ -12,81 +18,77 @@ export const urlSyncMixin = <T extends Constructor<HassBaseEl>>(
|
||||
__DEMO__
|
||||
? superClass
|
||||
: class extends superClass {
|
||||
private _ignoreNextHassChange = false;
|
||||
|
||||
private _ignoreNextPopstate = false;
|
||||
|
||||
private _moreInfoOpenedFromPath?: string;
|
||||
private _ignoreNextPopState = false;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
window.addEventListener("popstate", this._popstateChangeListener);
|
||||
this.addEventListener("dialog-closed", this._dialogClosedListener);
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener("popstate", this._popstateChangeListener);
|
||||
this.removeEventListener("dialog-closed", this._dialogClosedListener);
|
||||
}
|
||||
|
||||
protected hassChanged(newHass, oldHass): void {
|
||||
super.hassChanged(newHass, oldHass);
|
||||
|
||||
if (this._ignoreNextHassChange) {
|
||||
if (DEBUG) {
|
||||
console.log("ignore hasschange");
|
||||
}
|
||||
this._ignoreNextHassChange = false;
|
||||
return;
|
||||
}
|
||||
private _dialogClosedListener = (
|
||||
ev: HASSDomEvent<DialogClosedParams>
|
||||
) => {
|
||||
// If not closed by navigating back, and not a new dialog is open, remove the open state from history
|
||||
if (
|
||||
!oldHass ||
|
||||
oldHass.moreInfoEntityId === newHass.moreInfoEntityId
|
||||
history.state?.open &&
|
||||
history.state?.dialog === ev.detail.dialog
|
||||
) {
|
||||
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;
|
||||
this._ignoreNextPopState = true;
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private _popstateChangeListener = (ev) => {
|
||||
if (this._ignoreNextPopstate) {
|
||||
if (DEBUG) {
|
||||
console.log("ignore popstate");
|
||||
}
|
||||
this._ignoreNextPopstate = false;
|
||||
private _popstateChangeListener = (ev: PopStateEvent) => {
|
||||
if (this._ignoreNextPopState) {
|
||||
this._ignoreNextPopState = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("popstate", ev);
|
||||
}
|
||||
|
||||
if (this.hass && this.hass.moreInfoEntityId) {
|
||||
if (ev.state && "dialog" in ev.state) {
|
||||
if (DEBUG) {
|
||||
console.log("deselect entity");
|
||||
console.log("popstate", ev);
|
||||
}
|
||||
this._ignoreNextHassChange = true;
|
||||
fireEvent(this, "hass-more-info", { entityId: null });
|
||||
this._handleDialogStateChange(ev.state);
|
||||
}
|
||||
};
|
||||
|
||||
private async _handleDialogStateChange(state: DialogState) {
|
||||
if (DEBUG) {
|
||||
console.log("handle state", state);
|
||||
}
|
||||
if (!state.open) {
|
||||
const closed = await closeDialog(state.dialog);
|
||||
if (!closed) {
|
||||
// dialog could not be closed, push state again
|
||||
history.pushState(
|
||||
{
|
||||
dialog: state.dialog,
|
||||
open: true,
|
||||
dialogParams: null,
|
||||
oldState: null,
|
||||
},
|
||||
""
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (state.oldState) {
|
||||
this._handleDialogStateChange(state.oldState);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (state.dialogParams !== null) {
|
||||
showDialog(
|
||||
this,
|
||||
this.shadowRoot!,
|
||||
state.dialog,
|
||||
state.dialogParams
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user