diff --git a/src/dialogs/make-dialog-manager.ts b/src/dialogs/make-dialog-manager.ts index 3d90a421f6..9cfb685ad0 100644 --- a/src/dialogs/make-dialog-manager.ts +++ b/src/dialogs/make-dialog-manager.ts @@ -62,7 +62,7 @@ export const showDialog = async ( dialogParams: unknown, dialogImport?: () => Promise, addHistory = true -) => { +): Promise => { if (!(dialogTag in LOADED)) { if (!dialogImport) { if (__DEV__) { @@ -71,7 +71,7 @@ export const showDialog = async ( "Asked to show dialog that's not loaded and can't be imported" ); } - return; + return false; } LOADED[dialogTag] = { element: dialogImport().then(() => { @@ -128,6 +128,8 @@ export const showDialog = async ( // so it's guaranteed to be on top of the other elements root.appendChild(dialogElement); dialogElement.showDialog(dialogParams); + + return true; }; export const replaceDialog = (dialogElement: HassDialog) => { diff --git a/src/external_app/external_app_entrypoint.ts b/src/external_app/external_app_entrypoint.ts index e39ca5b566..39176b652b 100644 --- a/src/external_app/external_app_entrypoint.ts +++ b/src/external_app/external_app_entrypoint.ts @@ -6,6 +6,7 @@ This is the entry point for providing external app stuff from app entrypoint. */ import { fireEvent } from "../common/dom/fire_event"; +import { mainWindow } from "../common/dom/get_main_window"; import { HomeAssistantMain } from "../layouts/home-assistant-main"; import type { EMIncomingMessageCommands } from "./external_messaging"; @@ -45,6 +46,15 @@ const handleExternalMessage = ( result: null, }); } else if (msg.command === "sidebar/toggle") { + if (mainWindow.history.state?.open) { + bus.fireMessage({ + id: msg.id, + type: "result", + success: false, + error: { code: "not_allowed", message: "dialog open" }, + }); + return true; + } fireEvent(hassMainEl, "hass-toggle-menu"); bus.fireMessage({ id: msg.id, @@ -53,6 +63,15 @@ const handleExternalMessage = ( result: null, }); } else if (msg.command === "sidebar/show") { + if (mainWindow.history.state?.open) { + bus.fireMessage({ + id: msg.id, + type: "result", + success: false, + error: { code: "not_allowed", message: "dialog open" }, + }); + return true; + } fireEvent(hassMainEl, "hass-toggle-menu", { open: true }); bus.fireMessage({ id: msg.id, diff --git a/src/state/url-sync-mixin.ts b/src/state/url-sync-mixin.ts index d8cc554b75..387bf8fd9b 100644 --- a/src/state/url-sync-mixin.ts +++ b/src/state/url-sync-mixin.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import { ReactiveElement } from "lit"; +import { PropertyValueMap, ReactiveElement } from "lit"; import { HASSDomEvent } from "../common/dom/fire_event"; import { mainWindow } from "../common/dom/get_main_window"; import { @@ -31,8 +31,11 @@ export const urlSyncMixin = < public connectedCallback(): void { super.connectedCallback(); - if (history.length === 1) { - history.replaceState({ ...history.state, root: true }, ""); + if (mainWindow.history.length === 1) { + mainWindow.history.replaceState( + { ...mainWindow.history.state, root: true }, + "" + ); } mainWindow.addEventListener("popstate", this._popstateChangeListener); this.addEventListener("dialog-closed", this._dialogClosedListener); @@ -47,6 +50,15 @@ export const urlSyncMixin = < this.removeEventListener("dialog-closed", this._dialogClosedListener); } + protected firstUpdated( + changedProperties: PropertyValueMap | Map + ): void { + super.firstUpdated(changedProperties); + if (mainWindow.history.state?.dialog) { + this._handleDialogStateChange(mainWindow.history.state); + } + } + private _dialogClosedListener = ( ev: HASSDomEvent ) => { @@ -67,7 +79,7 @@ export const urlSyncMixin = < if (DEBUG) { console.log("remove state", ev.detail.dialog); } - if (history.length) { + if (mainWindow.history.length) { this._ignoreNextPopState = true; historyPromise = new Promise((resolve) => { historyResolve = () => { @@ -145,13 +157,21 @@ export const urlSyncMixin = < } return; } - if (state.dialogParams !== null) { - showDialog( + let shown = false; + if (state.open && state.dialogParams !== null) { + shown = await showDialog( this, this.shadowRoot!, state.dialog, state.dialogParams ); } + if (!shown) { + // can't open dialog, update state + mainWindow.history.replaceState( + { ...mainWindow.history.state, open: false }, + "" + ); + } } };