Handle setTimeout called when tab is shown (#6257)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Paulus Schoutsen 2020-06-29 14:29:05 -07:00 committed by GitHub
parent 7b0e743eca
commit 71faaf2ab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 46 deletions

View File

@ -76,11 +76,15 @@ export class HomeAssistantAppEl extends HassElement {
// @ts-ignore // @ts-ignore
this._loadHassTranslations(this.hass!.language, "state"); this._loadHassTranslations(this.hass!.language, "state");
this.addEventListener("unsuspend-app", () => this._onVisible(), false);
document.addEventListener( document.addEventListener(
"visibilitychange", "visibilitychange",
() => this._handleVisibilityChange(), () => this._checkVisibility(),
false false
); );
document.addEventListener("freeze", () => this._suspendApp());
document.addEventListener("resume", () => this._checkVisibility());
} }
protected hassReconnected() { protected hassReconnected() {
@ -148,30 +152,53 @@ export class HomeAssistantAppEl extends HassElement {
: route.path.substr(1, dividerPos - 1); : route.path.substr(1, dividerPos - 1);
} }
protected _handleVisibilityChange() { protected _checkVisibility() {
if (document.hidden) { if (document.hidden) {
// If the document is hidden, we will prevent reconnects until we are visible again // If the document is hidden, we will prevent reconnects until we are visible again
this.hass!.connection.suspendReconnectUntil( this._onHidden();
new Promise((resolve) => {
this._visiblePromiseResolve = resolve;
})
);
// We close the connection to Home Assistant after being hidden for 5 minutes
this._hiddenTimeout = window.setTimeout(() => {
this._hiddenTimeout = undefined;
this.hass!.connection.suspend();
}, 300000);
} else { } else {
// Clear timer to close the connection this._onVisible();
if (this._hiddenTimeout) { }
clearTimeout(this._hiddenTimeout); }
this._hiddenTimeout = undefined;
} private _onHidden() {
// Unsuspend the reconnect if (this._visiblePromiseResolve) {
if (this._visiblePromiseResolve) { return;
this._visiblePromiseResolve(); }
this._visiblePromiseResolve = undefined; this.hass!.connection.suspendReconnectUntil(
new Promise((resolve) => {
this._visiblePromiseResolve = resolve;
})
);
// We close the connection to Home Assistant after being hidden for 5 minutes
this._hiddenTimeout = window.setTimeout(() => {
this._hiddenTimeout = undefined;
// setTimeout can be delayed in the background and only fire
// when we switch to the tab or app again (Hey Android!)
if (!document.hidden) {
this._suspendApp();
} }
}, 300000);
window.addEventListener("focus", () => this._onVisible(), { once: true });
}
private _suspendApp() {
if (!this.hass!.connection.connected) {
return;
}
this.hass!.connection.suspend();
}
private _onVisible() {
// Clear timer to close the connection
if (this._hiddenTimeout) {
clearTimeout(this._hiddenTimeout);
this._hiddenTimeout = undefined;
}
// Unsuspend the reconnect
if (this._visiblePromiseResolve) {
this._visiblePromiseResolve();
this._visiblePromiseResolve = undefined;
} }
} }
} }

View File

@ -99,11 +99,13 @@ class PartialPanelResolver extends HassRouterPage {
protected firstUpdated(changedProps: PropertyValues) { protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
// Attach listeners for visibility
document.addEventListener( document.addEventListener(
"visibilitychange", "visibilitychange",
() => this._handleVisibilityChange(), () => this._checkVisibility(),
false false
); );
document.addEventListener("resume", () => this._checkVisibility());
} }
protected updated(changedProps: PropertyValues) { protected updated(changedProps: PropertyValues) {
@ -156,34 +158,48 @@ class PartialPanelResolver extends HassRouterPage {
} }
} }
private _handleVisibilityChange() { private _checkVisibility() {
if (document.hidden) { if (document.hidden) {
this._hiddenTimeout = window.setTimeout(() => { this._onHidden();
this._hiddenTimeout = undefined;
const curPanel = this.hass.panels[this._currentPage];
if (
this.lastChild &&
// iFrames will lose their state when disconnected
// Do not disconnect any iframe panel
curPanel.component_name !== "iframe" &&
// Do not disconnect any custom panel that embeds into iframe (ie hassio)
(curPanel.component_name !== "custom" ||
!(curPanel.config as CustomPanelInfo).config._panel_custom
.embed_iframe)
) {
this._disconnectedPanel = this.lastChild;
this.removeChild(this.lastChild);
}
}, 300000);
} else { } else {
if (this._hiddenTimeout) { this._onVisible();
clearTimeout(this._hiddenTimeout); }
this._hiddenTimeout = undefined; }
private _onHidden() {
this._hiddenTimeout = window.setTimeout(() => {
this._hiddenTimeout = undefined;
// setTimeout can be delayed in the background and only fire
// when we switch to the tab or app again (Hey Android!)
if (!document.hidden) {
return;
} }
if (this._disconnectedPanel) { const curPanel = this.hass.panels[this._currentPage];
this.appendChild(this._disconnectedPanel); if (
this._disconnectedPanel = undefined; this.lastChild &&
// iFrames will lose their state when disconnected
// Do not disconnect any iframe panel
curPanel.component_name !== "iframe" &&
// Do not disconnect any custom panel that embeds into iframe (ie hassio)
(curPanel.component_name !== "custom" ||
!(curPanel.config as CustomPanelInfo).config._panel_custom
.embed_iframe)
) {
this._disconnectedPanel = this.lastChild;
this.removeChild(this.lastChild);
} }
}, 300000);
window.addEventListener("focus", () => this._onVisible(), { once: true });
}
private _onVisible() {
if (this._hiddenTimeout) {
clearTimeout(this._hiddenTimeout);
this._hiddenTimeout = undefined;
}
if (this._disconnectedPanel) {
this.appendChild(this._disconnectedPanel);
this._disconnectedPanel = undefined;
} }
} }