Migrate dialog restart to ha-md-dialog (#22032)

* Fix ha-md-dialog for iOS 12

* Fix ha-md-dialog polyfill loading

* Fix ha-md-dialog open prop

* Fix multiple polyfill loads in ha-md-dialog

* Migrate dialog-restart to ha-md-dialog

* Fix dialog-restart to use ha-md-list

* Fix dialog opens dialog for ha-md-dialog
This commit is contained in:
Wendelin 2024-09-23 17:18:00 +02:00 committed by GitHub
parent 0c2a9d85e0
commit 3a9f09cb47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 191 additions and 170 deletions

View File

@ -7,6 +7,40 @@ import {
import { css } from "lit"; import { css } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
// workaround to be able to overlay an dialog with another dialog
MdDialog.addInitializer(async (instance) => {
await instance.updateComplete;
const dialogInstance = instance as MdDialog;
// @ts-expect-error dialog is private
dialogInstance.dialog.prepend(dialogInstance.scrim);
// @ts-expect-error scrim is private
dialogInstance.scrim.style.inset = 0;
// @ts-expect-error scrim is private
dialogInstance.scrim.style.zIndex = 0;
const { getOpenAnimation, getCloseAnimation } = dialogInstance;
dialogInstance.getOpenAnimation = () => {
const animations = getOpenAnimation.call(this);
animations.container = [
...(animations.container ?? []),
...(animations.dialog ?? []),
];
animations.dialog = [];
return animations;
};
dialogInstance.getCloseAnimation = () => {
const animations = getCloseAnimation.call(this);
animations.container = [
...(animations.container ?? []),
...(animations.dialog ?? []),
];
animations.dialog = [];
return animations;
};
});
let DIALOG_POLYFILL: Promise<typeof import("dialog-polyfill")>; let DIALOG_POLYFILL: Promise<typeof import("dialog-polyfill")>;
/** /**
@ -25,7 +59,6 @@ export class HaMdDialog extends MdDialog {
constructor() { constructor() {
super(); super();
this.addEventListener("cancel", this._handleCancel); this.addEventListener("cancel", this._handleCancel);
if (typeof HTMLDialogElement !== "function") { if (typeof HTMLDialogElement !== "function") {
@ -40,6 +73,11 @@ export class HaMdDialog extends MdDialog {
if (this.animate === undefined) { if (this.animate === undefined) {
this.quick = true; this.quick = true;
} }
// if browser doesn't support animate API disable open/close animations
if (this.animate === undefined) {
this.quick = true;
}
} }
// prevent open in older browsers and wait for polyfill to load // prevent open in older browsers and wait for polyfill to load
@ -80,7 +118,7 @@ export class HaMdDialog extends MdDialog {
_handleCancel(closeEvent: Event) { _handleCancel(closeEvent: Event) {
if (this.disableCancelAction) { if (this.disableCancelAction) {
closeEvent.preventDefault(); closeEvent.preventDefault();
const dialogElement = this.shadowRoot?.querySelector("dialog"); const dialogElement = this.shadowRoot?.querySelector("dialog .container");
if (this.animate !== undefined) { if (this.animate !== undefined) {
dialogElement?.animate( dialogElement?.animate(
[ [
@ -144,6 +182,9 @@ export class HaMdDialog extends MdDialog {
display: contents; display: contents;
} }
slot[name="content"]::slotted(*) {
padding: var(--dialog-content-padding, 24px);
}
.scrim { .scrim {
z-index: 10; // overlay navigation z-index: 10; // overlay navigation
} }

View File

@ -1,20 +1,21 @@
import "@material/mwc-list/mwc-list";
import { import {
mdiAutoFix, mdiAutoFix,
mdiLifebuoy, mdiLifebuoy,
mdiPower, mdiPower,
mdiPowerCycle, mdiPowerCycle,
mdiRefresh, mdiRefresh,
mdiClose,
} from "@mdi/js"; } from "@mdi/js";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state, query } from "lit/decorators";
import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
import "../../components/ha-circular-progress"; import "../../components/ha-circular-progress";
import { createCloseHeading } from "../../components/ha-dialog"; import "../../components/ha-md-dialog";
import type { HaMdDialog } from "../../components/ha-md-dialog";
import "../../components/ha-md-list";
import "../../components/ha-expansion-panel"; import "../../components/ha-expansion-panel";
import "../../components/ha-list-item"; import "../../components/ha-md-list-item";
import { import {
extractApiErrorMessage, extractApiErrorMessage,
ignoreSupervisorError, ignoreSupervisorError,
@ -45,6 +46,8 @@ class DialogRestart extends LitElement {
@state() @state()
private _hostInfo?: HassioHostInfo; private _hostInfo?: HassioHostInfo;
@query("ha-md-dialog") private _dialog?: HaMdDialog;
public async showDialog(): Promise<void> { public async showDialog(): Promise<void> {
const isHassioLoaded = isComponentLoaded(this.hass, "hassio"); const isHassioLoaded = isComponentLoaded(this.hass, "hassio");
@ -62,12 +65,16 @@ class DialogRestart extends LitElement {
} }
} }
public closeDialog(): void { private _dialogClosed(): void {
this._open = false; this._open = false;
this._loadingHostInfo = false; this._loadingHostInfo = false;
fireEvent(this, "dialog-closed", { dialog: this.localName }); fireEvent(this, "dialog-closed", { dialog: this.localName });
} }
public closeDialog(): void {
this._dialog?.close();
}
protected render() { protected render() {
if (!this._open) { if (!this._open) {
return nothing; return nothing;
@ -76,157 +83,145 @@ class DialogRestart extends LitElement {
const showReload = this.hass.userData?.showAdvanced; const showReload = this.hass.userData?.showAdvanced;
const showRebootShutdown = !!this._hostInfo; const showRebootShutdown = !!this._hostInfo;
const dialogTitle = this.hass.localize("ui.dialogs.restart.heading");
return html` return html`
<ha-dialog <ha-md-dialog open @closed=${this._dialogClosed}>
open <ha-dialog-header slot="headline">
@closed=${this.closeDialog} <ha-icon-button
hideActions slot="navigationIcon"
.heading=${!this._loadingHostInfo .label=${this.hass.localize("ui.dialogs.generic.close") ?? "Close"}
? createCloseHeading( .path=${mdiClose}
this.hass, @click=${this.closeDialog}
this.hass.localize("ui.dialogs.restart.heading") ></ha-icon-button>
) <span slot="title" .title=${dialogTitle}> ${dialogTitle} </span>
: undefined} </ha-dialog-header>
> <div slot="content" class="content">
${this._loadingHostInfo ${this._loadingHostInfo
? html` ? html`
<div class="loader"> <div class="loader">
<ha-circular-progress indeterminate></ha-circular-progress> <ha-circular-progress indeterminate></ha-circular-progress>
</div> </div>
` `
: html` : html`
<mwc-list dialogInitialFocus> <ha-md-list dialogInitialFocus>
${showReload ${showReload
? html`
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
@request-selected=${this._reload}
>
<div slot="graphic" class="icon-background reload">
<ha-svg-icon .path=${mdiAutoFix}></ha-svg-icon>
</div>
<span>
${this.hass.localize(
"ui.dialogs.restart.reload.title"
)}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.reload.description"
)}
</span>
</ha-list-item>
`
: nothing}
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
@request-selected=${this._restart}
>
<div slot="graphic" class="icon-background restart">
<ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
</div>
<span>
${this.hass.localize("ui.dialogs.restart.restart.title")}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.restart.description"
)}
</span>
</ha-list-item>
</mwc-list>
<ha-expansion-panel
.header=${this.hass.localize(
"ui.dialogs.restart.advanced_options"
)}
>
<mwc-list>
${showRebootShutdown
? html` ? html`
<ha-list-item <ha-md-list-item type="button" @click=${this._reload}>
graphic="avatar" <div slot="headline">
twoline ${this.hass.localize(
multiline-secondary "ui.dialogs.restart.reload.title"
hasMeta )}
@request-selected=${this._hostReboot}
>
<div slot="graphic" class="icon-background reboot">
<ha-svg-icon .path=${mdiPowerCycle}></ha-svg-icon>
</div> </div>
<span> <div slot="supporting-text">
${this.hass.localize( ${this.hass.localize(
"ui.dialogs.restart.reboot.title" "ui.dialogs.restart.reload.description"
)} )}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.reboot.description"
)}
</span>
</ha-list-item>
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
hasMeta
@request-selected=${this._hostShutdown}
>
<div slot="graphic" class="icon-background shutdown">
<ha-svg-icon .path=${mdiPower}></ha-svg-icon>
</div> </div>
<span> <div slot="start" class="icon-background reload">
${this.hass.localize( <ha-svg-icon .path=${mdiAutoFix}></ha-svg-icon>
"ui.dialogs.restart.shutdown.title" </div>
)} <ha-icon-next slot="end"></ha-icon-next>
</span> </ha-md-list-item>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.shutdown.description"
)}
</span>
</ha-list-item>
` `
: nothing} : nothing}
<ha-list-item <ha-md-list-item
graphic="avatar" type="button"
twoline @click=${this._showRestartDialog}
multiline-secondary
hasMeta
@request-selected=${this._restartSafeMode}
> >
<div <div slot="start" class="icon-background restart">
slot="graphic" <ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
class="icon-background restart-safe-mode"
>
<ha-svg-icon .path=${mdiLifebuoy}></ha-svg-icon>
</div> </div>
<span> <div slot="headline">
${this.hass.localize("ui.dialogs.restart.restart.title")}
</div>
<div slot="supporting-text">
${this.hass.localize( ${this.hass.localize(
"ui.dialogs.restart.restart-safe-mode.title" "ui.dialogs.restart.restart.description"
)} )}
</span> </div>
<span slot="secondary"> <ha-icon-next slot="end"></ha-icon-next>
${this.hass.localize( </ha-md-list-item>
"ui.dialogs.restart.restart-safe-mode.description" </ha-md-list>
)} <ha-expansion-panel
</span> .header=${this.hass.localize(
</ha-list-item> "ui.dialogs.restart.advanced_options"
</mwc-list> )}
</ha-expansion-panel> >
`} <ha-md-list>
</ha-dialog> ${showRebootShutdown
? html`
<ha-md-list-item
type="button"
@click=${this._hostReboot}
>
<div slot="start" class="icon-background reboot">
<ha-svg-icon .path=${mdiPowerCycle}></ha-svg-icon>
</div>
<div slot="headline">
${this.hass.localize(
"ui.dialogs.restart.reboot.title"
)}
</div>
<div slot="supporting-text">
${this.hass.localize(
"ui.dialogs.restart.reboot.description"
)}
</div>
<ha-icon-next slot="end"></ha-icon-next>
</ha-md-list-item>
<ha-md-list-item
type="button"
@click=${this._hostShutdown}
>
<div slot="start" class="icon-background shutdown">
<ha-svg-icon .path=${mdiPower}></ha-svg-icon>
</div>
<div slot="headline">
${this.hass.localize(
"ui.dialogs.restart.shutdown.title"
)}
</div>
<div slot="supporting-text">
${this.hass.localize(
"ui.dialogs.restart.shutdown.description"
)}
</div>
<ha-icon-next slot="end"></ha-icon-next>
</ha-md-list-item>
`
: nothing}
<ha-md-list-item
type="button"
@click=${this._showRestartSafeModeDialog}
>
<div
slot="start"
class="icon-background restart-safe-mode"
>
<ha-svg-icon .path=${mdiLifebuoy}></ha-svg-icon>
</div>
<div slot="headline">
${this.hass.localize(
"ui.dialogs.restart.restart-safe-mode.title"
)}
</div>
<div slot="supporting-text">
${this.hass.localize(
"ui.dialogs.restart.restart-safe-mode.description"
)}
</div>
<ha-icon-next slot="end"></ha-icon-next>
</ha-md-list-item>
</ha-md-list>
</ha-expansion-panel>
`}
</div>
</ha-md-dialog>
`; `;
} }
private async _reload(ev) { private async _reload() {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
this.closeDialog(); this.closeDialog();
showToast(this, { showToast(this, {
@ -244,13 +239,6 @@ class DialogRestart extends LitElement {
} }
} }
private async _restart(ev) {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
this._showRestartDialog();
}
private async _showRestartDialog() { private async _showRestartDialog() {
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize("ui.dialogs.restart.restart.confirm_title"), title: this.hass.localize("ui.dialogs.restart.restart.confirm_title"),
@ -279,13 +267,6 @@ class DialogRestart extends LitElement {
} }
} }
private async _restartSafeMode(ev) {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
this._showRestartSafeModeDialog();
}
private async _showRestartSafeModeDialog() { private async _showRestartSafeModeDialog() {
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize( title: this.hass.localize(
@ -320,10 +301,7 @@ class DialogRestart extends LitElement {
} }
} }
private async _hostReboot(ev): Promise<void> { private async _hostReboot(): Promise<void> {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize("ui.dialogs.restart.reboot.confirm_title"), title: this.hass.localize("ui.dialogs.restart.reboot.confirm_title"),
text: this.hass.localize("ui.dialogs.restart.reboot.confirm_description"), text: this.hass.localize("ui.dialogs.restart.reboot.confirm_description"),
@ -357,10 +335,7 @@ class DialogRestart extends LitElement {
} }
} }
private async _hostShutdown(ev): Promise<void> { private async _hostShutdown(): Promise<void> {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize("ui.dialogs.restart.shutdown.confirm_title"), title: this.hass.localize("ui.dialogs.restart.shutdown.confirm_title"),
text: this.hass.localize( text: this.hass.localize(
@ -401,13 +376,13 @@ class DialogRestart extends LitElement {
haStyle, haStyle,
haStyleDialog, haStyleDialog,
css` css`
ha-dialog { ha-md-dialog {
--dialog-content-padding: 0; --dialog-content-padding: 0;
} }
@media all and (min-width: 550px) { @media all and (min-width: 550px) {
ha-dialog { ha-md-dialog {
--mdc-dialog-min-width: 500px; min-width: 500px;
--mdc-dialog-max-width: 500px; max-width: 500px;
} }
} }
@ -425,6 +400,11 @@ class DialogRestart extends LitElement {
border-radius: 50%; border-radius: 50%;
color: #fff; color: #fff;
display: flex; display: flex;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
} }
.reload { .reload {
background-color: #5f8a49; background-color: #5f8a49;