Close dialogs on history back (#6354)

This commit is contained in:
Bram Kragten
2020-07-12 22:19:26 +02:00
committed by GitHub
parent 3bc54aa9e0
commit 3d32e6310d
10 changed files with 236 additions and 146 deletions

View File

@@ -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);
}
);
};