Compare commits

...
3 changed files with 52 additions and 2 deletions

No files matched your search

+5 -1
View File
@@ -1,4 +1,7 @@
import { closeAllDialogs } from "../dialogs/make-dialog-manager";
import {
closeAllDialogs,
updateClosedDialogSearch,
} from "../dialogs/make-dialog-manager";
import { fireEvent } from "./dom/fire_event";
import { mainWindow } from "./dom/get_main_window";
import { currentPath } from "./url/current-path";
@@ -42,6 +45,7 @@ export const updateHistoryState = (patch: Record<string, unknown>) => {
*/
export const replaceCurrentUrl = (url: string) => {
mainWindow.history.replaceState(mainWindow.history.state, "", url);
updateClosedDialogSearch();
rememberCurrentEntry();
};
+40
View File
@@ -65,6 +65,9 @@ const LOADED: LoadedDialogsDict = {};
const OPEN_DIALOG_STACK: DialogState[] = [];
export const FOCUS_TARGET = Symbol.for("HA focus target");
/** The URL of the last dialog's entry, when the dialog went back to close. */
let closedDialogUrl: { pathname: string; search: string } | undefined;
/**
* Shows a dialog element, lazy-loading it if needed, and optionally integrates
* dialog open/close behavior with browser history.
@@ -240,6 +243,41 @@ export const closeLastDialog = async (historyState?: any) => {
return true;
};
/**
* Called on the back() of a dialog that closed itself. The page's entry still
* has the URL from before the dialog opened, so a change to the search made
* while it was open, like a filter written after a delete, is kept. Must run
* before anything else reads the URL on that popstate.
*/
export const restoreClosedDialogSearch = () => {
const closedUrl = closedDialogUrl;
closedDialogUrl = undefined;
const { history, location } = mainWindow;
if (
closedUrl?.pathname === location.pathname &&
closedUrl.search !== location.search
) {
history.replaceState(
history.state,
"",
`${location.pathname}${closedUrl.search}${location.hash}`
);
}
};
/**
* Called after the current entry's URL is rewritten. Until the back() of a
* closed dialog lands, that is still the dialog's entry, so keep its search
* for restoreClosedDialogSearch().
*/
export const updateClosedDialogSearch = () => {
if (closedDialogUrl) {
const { pathname, search } = mainWindow.location;
closedDialogUrl = { pathname, search };
}
};
export const closeAllDialogs = async () => {
for (let i = OPEN_DIALOG_STACK.length - 1; i >= 0; i--) {
const closed =
@@ -270,6 +308,8 @@ const _handleClosed = (ev: HASSDomEvent<DialogClosedParams>) => {
);
} else if (dialogIndex !== -1) {
// if the dialog is the last one and it was indeed open, go back
const { pathname, search } = mainWindow.location;
closedDialogUrl = { pathname, search };
mainWindow.history.back();
}
}
+7 -1
View File
@@ -3,7 +3,10 @@ import type { ReactiveElement, PropertyValues } from "lit";
import { fireEvent } from "../common/dom/fire_event";
import { mainWindow } from "../common/dom/get_main_window";
import { updateHistoryState } from "../common/navigate";
import { closeLastDialog } from "../dialogs/make-dialog-manager";
import {
closeLastDialog,
restoreClosedDialogSearch,
} from "../dialogs/make-dialog-manager";
import type { ProvideHassElement } from "../mixins/provide-hass-lit-mixin";
import type { Constructor } from "../types";
@@ -64,6 +67,9 @@ export const urlSyncMixin = <
console.log("popstate", ev);
}
if (ev.state.opensDialog) {
// This listener is added before any page's, so pages read the
// restored URL
restoreClosedDialogSearch();
// coming back from a dialog
// if we are instead navigating forward, the dialogs are already closed
closeLastDialog();