Make chrome work-around work in iframes (#9200)

This commit is contained in:
Bram Kragten 2021-05-21 09:09:31 +02:00 committed by GitHub
parent 9328576b55
commit fd9bb4d8cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 79 additions and 40 deletions

View File

@ -20,6 +20,7 @@ import {
showAlertDialog, showAlertDialog,
showConfirmationDialog, showConfirmationDialog,
} from "../../../../src/dialogs/generic/show-dialog-box"; } from "../../../../src/dialogs/generic/show-dialog-box";
import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
import { PolymerChangedEvent } from "../../../../src/polymer-types"; import { PolymerChangedEvent } from "../../../../src/polymer-types";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles"; import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types"; import { HomeAssistant } from "../../../../src/types";
@ -68,7 +69,9 @@ interface FolderItem {
} }
@customElement("dialog-hassio-snapshot") @customElement("dialog-hassio-snapshot")
class HassioSnapshotDialog extends LitElement { class HassioSnapshotDialog
extends LitElement
implements HassDialog<HassioSnapshotDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public supervisor?: Supervisor; @property({ attribute: false }) public supervisor?: Supervisor;
@ -106,12 +109,21 @@ class HassioSnapshotDialog extends LitElement {
} }
} }
public closeDialog() {
this._dialogParams = undefined;
this._snapshot = undefined;
this._snapshotPassword = "";
this._folders = [];
this._addons = [];
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this._dialogParams || !this._snapshot) { if (!this._dialogParams || !this._snapshot) {
return html``; return html``;
} }
return html` return html`
<ha-dialog open @closing=${this._closeDialog} .heading=${true}> <ha-dialog open @closing=${this.closeDialog} .heading=${true}>
<div slot="heading"> <div slot="heading">
<ha-header-bar> <ha-header-bar>
<span slot="title"> ${this._computeName} </span> <span slot="title"> ${this._computeName} </span>
@ -359,7 +371,7 @@ class HassioSnapshotDialog extends LitElement {
.then( .then(
() => { () => {
alert("Snapshot restored!"); alert("Snapshot restored!");
this._closeDialog(); this.closeDialog();
}, },
(error) => { (error) => {
this._error = error.body.message; this._error = error.body.message;
@ -371,7 +383,7 @@ class HassioSnapshotDialog extends LitElement {
method: "POST", method: "POST",
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
this._closeDialog(); this.closeDialog();
} }
} }
@ -410,7 +422,7 @@ class HassioSnapshotDialog extends LitElement {
.then( .then(
() => { () => {
alert("Snapshot restored!"); alert("Snapshot restored!");
this._closeDialog(); this.closeDialog();
}, },
(error) => { (error) => {
this._error = error.body.message; this._error = error.body.message;
@ -422,7 +434,7 @@ class HassioSnapshotDialog extends LitElement {
method: "POST", method: "POST",
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
this._closeDialog(); this.closeDialog();
} }
} }
@ -445,7 +457,7 @@ class HassioSnapshotDialog extends LitElement {
if (this._dialogParams!.onDelete) { if (this._dialogParams!.onDelete) {
this._dialogParams!.onDelete(); this._dialogParams!.onDelete();
} }
this._closeDialog(); this.closeDialog();
}, },
(error) => { (error) => {
this._error = error.body.message; this._error = error.body.message;
@ -496,14 +508,6 @@ class HassioSnapshotDialog extends LitElement {
private get _computeSize() { private get _computeSize() {
return Math.ceil(this._snapshot!.size * 10) / 10 + " MB"; return Math.ceil(this._snapshot!.size * 10) / 10 + " MB";
} }
private _closeDialog() {
this._dialogParams = undefined;
this._snapshot = undefined;
this._snapshotPassword = "";
this._folders = [];
this._addons = [];
}
} }
declare global { declare global {

View File

@ -15,5 +15,11 @@ body {
padding: 0; padding: 0;
height: 100vh; height: 100vh;
} }
@media (prefers-color-scheme: dark) {
body {
background-color: #111111;
color: #e1e1e1;
}
}
`; `;
document.head.appendChild(styleEl); document.head.appendChild(styleEl);

View File

@ -4,6 +4,7 @@ import { atLeastVersion } from "../../src/common/config/version";
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event"; import { fireEvent } from "../../src/common/dom/fire_event";
import { isNavigationClick } from "../../src/common/dom/is-navigation-click"; import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
import { mainWindow } from "../../src/common/dom/get_main_window";
import { navigate } from "../../src/common/navigate"; import { navigate } from "../../src/common/navigate";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor"; import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
import { Supervisor } from "../../src/data/supervisor/supervisor"; import { Supervisor } from "../../src/data/supervisor/supervisor";
@ -50,7 +51,7 @@ export class HassioMain extends SupervisorBaseElement {
// Joakim - April 26, 2021 // Joakim - April 26, 2021
// Due to changes in behavior in Google Chrome, we changed navigate to listen on the top element // Due to changes in behavior in Google Chrome, we changed navigate to listen on the top element
top.addEventListener("location-changed", (ev) => mainWindow.addEventListener("location-changed", (ev) =>
// @ts-ignore // @ts-ignore
fireEvent(this, ev.type, ev.detail, { fireEvent(this, ev.type, ev.detail, {
bubbles: false, bubbles: false,

View File

@ -0,0 +1,8 @@
import { MAIN_WINDOW_NAME } from "../../data/main_window";
export const mainWindow =
window.name === MAIN_WINDOW_NAME
? window
: parent.name === MAIN_WINDOW_NAME
? parent
: top;

View File

@ -1,4 +1,5 @@
import { fireEvent } from "./dom/fire_event"; import { fireEvent } from "./dom/fire_event";
import { mainWindow } from "./dom/get_main_window";
declare global { declare global {
// for fire event // for fire event
@ -12,24 +13,24 @@ declare global {
export const navigate = (_node: any, path: string, replace = false) => { export const navigate = (_node: any, path: string, replace = false) => {
if (__DEMO__) { if (__DEMO__) {
if (replace) { if (replace) {
top.history.replaceState( mainWindow.history.replaceState(
top.history.state?.root ? { root: true } : null, mainWindow.history.state?.root ? { root: true } : null,
"", "",
`${top.location.pathname}#${path}` `${mainWindow.location.pathname}#${path}`
); );
} else { } else {
top.location.hash = path; mainWindow.location.hash = path;
} }
} else if (replace) { } else if (replace) {
top.history.replaceState( mainWindow.history.replaceState(
top.history.state?.root ? { root: true } : null, mainWindow.history.state?.root ? { root: true } : null,
"", "",
path path
); );
} else { } else {
top.history.pushState(null, "", path); mainWindow.history.pushState(null, "", path);
} }
fireEvent(top, "location-changed", { fireEvent(mainWindow, "location-changed", {
replace, replace,
}); });
}; };

1
src/data/main_window.ts Normal file
View File

@ -0,0 +1 @@
export const MAIN_WINDOW_NAME = "ha-main-window";

View File

@ -1,4 +1,5 @@
import { HASSDomEvent, ValidHassDomEvent } from "../common/dom/fire_event"; import { HASSDomEvent, ValidHassDomEvent } from "../common/dom/fire_event";
import { mainWindow } from "../common/dom/get_main_window";
import { ProvideHassElement } from "../mixins/provide-hass-lit-mixin"; import { ProvideHassElement } from "../mixins/provide-hass-lit-mixin";
declare global { declare global {
@ -67,25 +68,26 @@ export const showDialog = async (
} }
if (addHistory) { if (addHistory) {
top.history.replaceState( mainWindow.history.replaceState(
{ {
dialog: dialogTag, dialog: dialogTag,
open: false, open: false,
oldState: oldState:
top.history.state?.open && top.history.state?.dialog !== dialogTag mainWindow.history.state?.open &&
? top.history.state mainWindow.history.state?.dialog !== dialogTag
? mainWindow.history.state
: null, : null,
}, },
"" ""
); );
try { try {
top.history.pushState( mainWindow.history.pushState(
{ dialog: dialogTag, dialogParams: dialogParams, open: true }, { dialog: dialogTag, dialogParams: dialogParams, open: true },
"" ""
); );
} catch (err) { } catch (err) {
// dialogParams could not be cloned, probably contains callback // dialogParams could not be cloned, probably contains callback
top.history.pushState( mainWindow.history.pushState(
{ dialog: dialogTag, dialogParams: null, open: true }, { dialog: dialogTag, dialogParams: null, open: true },
"" ""
); );
@ -96,7 +98,10 @@ export const showDialog = async (
}; };
export const replaceDialog = () => { export const replaceDialog = () => {
top.history.replaceState({ ...top.history.state, replaced: true }, ""); mainWindow.history.replaceState(
{ ...mainWindow.history.state, replaced: true },
""
);
}; };
export const closeDialog = async (dialogTag: string): Promise<boolean> => { export const closeDialog = async (dialogTag: string): Promise<boolean> => {

View File

@ -25,6 +25,9 @@ import { subscribeUser } from "../data/ws-user";
import type { ExternalAuth } from "../external_app/external_auth"; import type { ExternalAuth } from "../external_app/external_auth";
import "../resources/safari-14-attachshadow-patch"; import "../resources/safari-14-attachshadow-patch";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import { MAIN_WINDOW_NAME } from "../data/main_window";
window.name = MAIN_WINDOW_NAME;
declare global { declare global {
interface Window { interface Window {

View File

@ -47,7 +47,13 @@ function initialize(
) { ) {
const style = document.createElement("style"); const style = document.createElement("style");
style.innerHTML = "body{margin:0}"; style.innerHTML = `body { margin:0; }
@media (prefers-color-scheme: dark) {
body {
background-color: #111111;
color: #e1e1e1;
}
}`;
document.head.appendChild(style); document.head.appendChild(style);
const config = panel.config._panel_custom; const config = panel.config._panel_custom;

View File

@ -1,6 +1,7 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import { ReactiveElement } from "lit"; import { ReactiveElement } from "lit";
import { HASSDomEvent } from "../common/dom/fire_event"; import { HASSDomEvent } from "../common/dom/fire_event";
import { mainWindow } from "../common/dom/get_main_window";
import { import {
closeDialog, closeDialog,
DialogClosedParams, DialogClosedParams,
@ -28,13 +29,16 @@ export const urlSyncMixin = <
if (history.length === 1) { if (history.length === 1) {
history.replaceState({ ...history.state, root: true }, ""); history.replaceState({ ...history.state, root: true }, "");
} }
top.addEventListener("popstate", this._popstateChangeListener); mainWindow.addEventListener("popstate", this._popstateChangeListener);
this.addEventListener("dialog-closed", this._dialogClosedListener); this.addEventListener("dialog-closed", this._dialogClosedListener);
} }
public disconnectedCallback(): void { public disconnectedCallback(): void {
super.disconnectedCallback(); super.disconnectedCallback();
top.removeEventListener("popstate", this._popstateChangeListener); mainWindow.removeEventListener(
"popstate",
this._popstateChangeListener
);
this.removeEventListener("dialog-closed", this._dialogClosedListener); this.removeEventListener("dialog-closed", this._dialogClosedListener);
} }
@ -45,21 +49,21 @@ export const urlSyncMixin = <
console.log("dialog closed", ev.detail.dialog); console.log("dialog closed", ev.detail.dialog);
console.log( console.log(
"open", "open",
top.history.state?.open, mainWindow.history.state?.open,
"dialog", "dialog",
top.history.state?.dialog mainWindow.history.state?.dialog
); );
} }
// If not closed by navigating back, and not a new dialog is open, remove the open state from history // If not closed by navigating back, and not a new dialog is open, remove the open state from history
if ( if (
top.history.state?.open && mainWindow.history.state?.open &&
top.history.state?.dialog === ev.detail.dialog mainWindow.history.state?.dialog === ev.detail.dialog
) { ) {
if (DEBUG) { if (DEBUG) {
console.log("remove state", ev.detail.dialog); console.log("remove state", ev.detail.dialog);
} }
this._ignoreNextPopState = true; this._ignoreNextPopState = true;
top.history.back(); mainWindow.history.back();
} }
}; };
@ -73,7 +77,7 @@ export const urlSyncMixin = <
if (DEBUG) { if (DEBUG) {
console.log("remove old state", ev.state.oldState); console.log("remove old state", ev.state.oldState);
} }
top.history.back(); mainWindow.history.back();
return; return;
} }
this._ignoreNextPopState = false; this._ignoreNextPopState = false;
@ -98,7 +102,7 @@ export const urlSyncMixin = <
console.log("dialog could not be closed"); console.log("dialog could not be closed");
} }
// dialog could not be closed, push state again // dialog could not be closed, push state again
top.history.pushState( mainWindow.history.pushState(
{ {
dialog: state.dialog, dialog: state.dialog,
open: true, open: true,