diff --git a/src/common/navigate.ts b/src/common/navigate.ts index 69710ebe1d..34c1663269 100644 --- a/src/common/navigate.ts +++ b/src/common/navigate.ts @@ -14,42 +14,46 @@ export interface NavigateOptions { data?: any; } -export const navigate = async (path: string, options?: NavigateOptions) => { - const { history } = mainWindow; - let replace = options?.replace || false; +export const navigate = async (path: string, options?: NavigateOptions) => + new Promise((resolve) => { + // need to wait for history state to be updated in case a dialog was closed before calling navigate + setTimeout(async () => { + const { history } = mainWindow; + let replace = options?.replace || false; + if (history.state?.dialog) { + const closed = await closeAllDialogs(); + if (!closed) { + // eslint-disable-next-line no-console + console.warn("Navigation blocked, because dialog refused to close"); + resolve(false); + return; + } + // if there were open dialogs, we discard the current state + replace = true; + } - if (history.state?.dialog) { - const closed = await closeAllDialogs(); - if (!closed) { - // eslint-disable-next-line no-console - console.warn("Navigation blocked, because dialog refused to close"); - return false; - } - // if there were open dialogs, we discard the current state - replace = true; - } - - if (__DEMO__) { - if (replace) { - history.replaceState( - history.state?.root ? { root: true } : (options?.data ?? null), - "", - `${mainWindow.location.pathname}#${path}` - ); - } else { - mainWindow.location.hash = path; - } - } else if (replace) { - history.replaceState( - history.state?.root ? { root: true } : (options?.data ?? null), - "", - path - ); - } else { - history.pushState(options?.data ?? null, "", path); - } - fireEvent(mainWindow, "location-changed", { - replace, + if (__DEMO__) { + if (replace) { + history.replaceState( + history.state?.root ? { root: true } : (options?.data ?? null), + "", + `${mainWindow.location.pathname}#${path}` + ); + } else { + mainWindow.location.hash = path; + } + } else if (replace) { + history.replaceState( + history.state?.root ? { root: true } : (options?.data ?? null), + "", + path + ); + } else { + history.pushState(options?.data ?? null, "", path); + } + fireEvent(mainWindow, "location-changed", { + replace, + }); + resolve(true); + }); }); - return true; -}; diff --git a/src/dialogs/make-dialog-manager.ts b/src/dialogs/make-dialog-manager.ts index dd96d79cda..0b18fc77da 100644 --- a/src/dialogs/make-dialog-manager.ts +++ b/src/dialogs/make-dialog-manager.ts @@ -171,11 +171,21 @@ export const closeLastDialog = async () => { "" ); } + return closed; } + return true; }; -export const closeAllDialogs = () => - Promise.all(OPEN_DIALOG_STACK.map((state) => closeDialog(state.dialogTag))); +export const closeAllDialogs = async () => { + while (OPEN_DIALOG_STACK.length) { + // eslint-disable-next-line no-await-in-loop + const closed = await closeLastDialog(); + if (!closed) { + return false; + } + } + return true; +}; const _handleClosed = async (ev: HASSDomEvent) => { // If not closed by navigating back, remove the open state from history