diff --git a/src/common/navigate.ts b/src/common/navigate.ts index e2e0f26dd0..a9d41ab04d 100644 --- a/src/common/navigate.ts +++ b/src/common/navigate.ts @@ -1,3 +1,4 @@ +import { historyPromise } from "../state/url-sync-mixin"; import { fireEvent } from "./dom/fire_event"; import { mainWindow } from "./dom/get_main_window"; @@ -15,6 +16,11 @@ export interface NavigateOptions { export const navigate = (path: string, options?: NavigateOptions) => { const replace = options?.replace || false; + if (historyPromise) { + historyPromise.then(() => navigate(path, options)); + return; + } + if (__DEMO__) { if (replace) { mainWindow.history.replaceState( diff --git a/src/panels/config/automation/dialog-new-automation.ts b/src/panels/config/automation/dialog-new-automation.ts index 3f00995b05..4c3b6723eb 100644 --- a/src/panels/config/automation/dialog-new-automation.ts +++ b/src/panels/config/automation/dialog-new-automation.ts @@ -2,7 +2,6 @@ import "@material/mwc-button"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../common/dom/fire_event"; -import { nextRender } from "../../../common/util/render-status"; import "../../../components/ha-blueprint-picker"; import "../../../components/ha-card"; import "../../../components/ha-circular-progress"; @@ -26,8 +25,10 @@ class DialogNewAutomation extends LitElement implements HassDialog { } public closeDialog(): void { + if (this._opened) { + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } this._opened = false; - fireEvent(this, "dialog-closed", { dialog: this.localName }); } protected render(): TemplateResult { @@ -66,8 +67,8 @@ class DialogNewAutomation extends LitElement implements HassDialog { "ui.panel.config.automation.dialog_new.start_empty_description" )} - + + `; @@ -75,7 +76,6 @@ class DialogNewAutomation extends LitElement implements HassDialog { private async _blueprintPicked(ev: CustomEvent) { this.closeDialog(); - await nextRender(); showAutomationEditor({ use_blueprint: { path: ev.detail.value } }); } @@ -85,7 +85,6 @@ class DialogNewAutomation extends LitElement implements HassDialog { private async _blank() { this.closeDialog(); - await nextRender(); showAutomationEditor(); } diff --git a/src/state/url-sync-mixin.ts b/src/state/url-sync-mixin.ts index 684f9a79dc..d8cc554b75 100644 --- a/src/state/url-sync-mixin.ts +++ b/src/state/url-sync-mixin.ts @@ -13,6 +13,11 @@ import { Constructor } from "../types"; const DEBUG = false; +// eslint-disable-next-line import/no-mutable-exports +export let historyPromise: Promise | undefined; + +let historyResolve: undefined | (() => void); + export const urlSyncMixin = < T extends Constructor >( @@ -62,16 +67,26 @@ export const urlSyncMixin = < if (DEBUG) { console.log("remove state", ev.detail.dialog); } - this._ignoreNextPopState = true; - mainWindow.history.back(); + if (history.length) { + this._ignoreNextPopState = true; + historyPromise = new Promise((resolve) => { + historyResolve = () => { + resolve(); + historyResolve = undefined; + historyPromise = undefined; + }; + mainWindow.history.back(); + }); + } } }; private _popstateChangeListener = (ev: PopStateEvent) => { if (this._ignoreNextPopState) { if ( - ev.state?.oldState?.replaced || - ev.state?.oldState?.dialogParams === null + history.length && + (ev.state?.oldState?.replaced || + ev.state?.oldState?.dialogParams === null) ) { // if the previous dialog was replaced, or we could not copy the params, and the current dialog is closed, we should also remove the previous dialog from history if (DEBUG) { @@ -80,7 +95,13 @@ export const urlSyncMixin = < mainWindow.history.back(); return; } + if (DEBUG) { + console.log("ignore popstate"); + } this._ignoreNextPopState = false; + if (historyResolve) { + historyResolve(); + } return; } if (ev.state && "dialog" in ev.state) { @@ -89,6 +110,9 @@ export const urlSyncMixin = < } this._handleDialogStateChange(ev.state); } + if (historyResolve) { + historyResolve(); + } }; private async _handleDialogStateChange(state: DialogState) {