diff --git a/src/panels/config/apps/app-view/info/supervisor-app-info.ts b/src/panels/config/apps/app-view/info/supervisor-app-info.ts index bf2df43292..036af25b20 100644 --- a/src/panels/config/apps/app-view/info/supervisor-app-info.ts +++ b/src/panels/config/apps/app-view/info/supervisor-app-info.ts @@ -4,8 +4,10 @@ import { mdiCircleOffOutline, mdiCursorDefaultClickOutline, mdiDocker, + mdiDotsVertical, mdiExclamationThick, mdiFlask, + mdiHammer, mdiKey, mdiLinkLock, mdiNetwork, @@ -19,7 +21,9 @@ import { mdiNumeric8, mdiPlayCircle, mdiPound, + mdiRestart, mdiShield, + mdiStop, } from "@mdi/js"; import type { CSSResultGroup, TemplateResult } from "lit"; import { LitElement, css, html, nothing } from "lit"; @@ -37,7 +41,10 @@ import "../../../../../components/chips/ha-chip-set"; import "../../../../../components/ha-alert"; import "../../../../../components/ha-button"; import "../../../../../components/ha-card"; +import "../../../../../components/ha-dropdown"; +import "../../../../../components/ha-dropdown-item"; import "../../../../../components/ha-formfield"; +import "../../../../../components/ha-icon-button"; import "../../../../../components/ha-markdown"; import "../../../../../components/ha-settings-row"; import "../../../../../components/ha-svg-icon"; @@ -119,15 +126,16 @@ class SupervisorAppInfo extends LitElement { @state() private _error?: string; - private _fetchDataTimeout?: number; + private _pollInterval?: number; + + public connectedCallback() { + super.connectedCallback(); + this._startPolling(); + } public disconnectedCallback() { super.disconnectedCallback(); - - if (this._fetchDataTimeout) { - clearTimeout(this._fetchDataTimeout); - this._fetchDataTimeout = undefined; - } + this._stopPolling(); } protected render(): TemplateResult { @@ -223,6 +231,69 @@ class SupervisorAppInfo extends LitElement { .path=${mdiCircleOffOutline} > `} + ${this._computeIsRunning || this.addon.build + ? html` + + + ${this._computeIsRunning + ? html` + + + ${this.hass.localize( + "ui.panel.config.apps.dashboard.stop" + )} + + + + ${this.hass.localize( + "ui.panel.config.apps.dashboard.restart" + )} + + ` + : nothing} + ${this.addon.build + ? html` + + + ${this.hass.localize( + "ui.panel.config.apps.dashboard.rebuild" + )} + + ` + : nothing} + + ` + : nothing} ` : html` ${this.addon.version_latest} `} @@ -654,44 +725,6 @@ class SupervisorAppInfo extends LitElement { : nothing}
-
- ${this.addon.version - ? this._computeIsRunning - ? html` - - ${this.hass.localize( - "ui.panel.config.apps.dashboard.stop" - )} - - - ${this.hass.localize( - "ui.panel.config.apps.dashboard.restart" - )} - - ` - : html` - - ${this.hass.localize( - "ui.panel.config.apps.dashboard.start" - )} - - ` - : nothing} -
${this.addon.version ? html` @@ -705,44 +738,48 @@ class SupervisorAppInfo extends LitElement { "ui.panel.config.apps.dashboard.uninstall" )} - ${this.addon.build - ? html` - - ${this.hass.localize( - "ui.panel.config.apps.dashboard.rebuild" - )} - - ` - : nothing} - ${this._computeShowWebUI || this._computeShowIngressUI - ? html` - - ${this.hass.localize( - "ui.panel.config.apps.dashboard.open_web_ui" - )} - - ` - : nothing} ` + : nothing} +
+
+ ${this.addon.version + ? this._computeIsRunning + ? html` + ${this._computeShowWebUI || this._computeShowIngressUI + ? html` + + ${this.hass.localize( + "ui.panel.config.apps.dashboard.open_web_ui" + )} + + ` + : nothing} + ` + : html` + + ${this.hass.localize( + "ui.panel.config.apps.dashboard.start" + )} + + ` : html` { - const addon = await fetchHassioAddonInfo(this.hass, this.addon.slug); - if (addon.state !== "startup") { - this._fetchDataTimeout = undefined; - this.addon = addon; - const eventdata = { - success: true, - response: undefined, - path: "start", - }; - fireEvent(this, "hass-api-called", eventdata); - } else { - this._scheduleDataUpdate(); - } - }, 500); + private _startPolling() { + if (this._pollInterval) { + return; + } + this._pollInterval = window.setInterval(() => { + this._refreshAddonInfo(); + }, 5000); } - private async _loadData(): Promise { + private _stopPolling() { + if (this._pollInterval) { + clearInterval(this._pollInterval); + this._pollInterval = undefined; + } + } + + private async _refreshAddonInfo(): Promise { + if (!this.addon?.slug) { + return; + } + try { + const addon = await fetchHassioAddonInfo(this.hass, this.addon.slug); + this.addon = addon; + } catch { + // Ignore errors during polling + } + } + + private async _loadMetrics(): Promise { if ("state" in this.addon && this.addon.state === "started") { this._metrics = await fetchHassioStats( this.hass, @@ -1069,14 +1107,11 @@ class SupervisorAppInfo extends LitElement { button.progress = false; } - private async _stopClicked(ev: CustomEvent): Promise { + private async _stopClicked(): Promise { if (this._isSystemManaged(this.addon) && !this.controlEnabled) { return; } - const button = ev.currentTarget as any; - button.progress = true; - try { await stopHassioAddon(this.hass, this.addon.slug); const eventdata = { @@ -1093,17 +1128,13 @@ class SupervisorAppInfo extends LitElement { text: extractApiErrorMessage(err), }); } - button.progress = false; } - private async _restartClicked(ev: CustomEvent): Promise { + private async _restartClicked(): Promise { if (this._isSystemManaged(this.addon) && !this.controlEnabled) { return; } - const button = ev.currentTarget as any; - button.progress = true; - try { await restartHassioAddon(this.hass, this.addon.slug); const eventdata = { @@ -1120,13 +1151,9 @@ class SupervisorAppInfo extends LitElement { text: extractApiErrorMessage(err), }); } - button.progress = false; } - private async _rebuildClicked(ev: CustomEvent): Promise { - const button = ev.currentTarget as any; - button.progress = true; - + private async _rebuildClicked(): Promise { try { await rebuildLocalAddon(this.hass, this.addon.slug); } catch (err: any) { @@ -1137,7 +1164,6 @@ class SupervisorAppInfo extends LitElement { text: extractApiErrorMessage(err), }); } - button.progress = false; } private async _startClicked(ev: CustomEvent): Promise { @@ -1318,7 +1344,8 @@ class SupervisorAppInfo extends LitElement { .addon-version { float: var(--float-end); font-size: var(--ha-font-size-l); - vertical-align: middle; + display: flex; + align-items: center; } .errors { color: var(--error-color);