Ingress: offer to start addon on ingress page (#16458)
Co-authored-by: Joakim Sørensen <ludeeus@ludeeus.dev>
This commit is contained in:
parent
343708cdaa
commit
b15754a6a7
|
@ -114,11 +114,22 @@ class HassioAddonInfo extends LitElement {
|
|||
|
||||
@state() private _error?: string;
|
||||
|
||||
private _fetchDataTimeout?: number;
|
||||
|
||||
private _addonStoreInfo = memoizeOne(
|
||||
(slug: string, storeAddons: StoreAddon[]) =>
|
||||
storeAddons.find((addon) => addon.slug === slug)
|
||||
);
|
||||
|
||||
public disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
|
||||
if (this._fetchDataTimeout) {
|
||||
clearInterval(this._fetchDataTimeout);
|
||||
this._fetchDataTimeout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const addonStoreInfo =
|
||||
!this.addon.detached && !this.addon.available
|
||||
|
@ -592,7 +603,10 @@ class HassioAddonInfo extends LitElement {
|
|||
</ha-progress-button>
|
||||
`
|
||||
: html`
|
||||
<ha-progress-button @click=${this._startClicked}>
|
||||
<ha-progress-button
|
||||
@click=${this._startClicked}
|
||||
.progress=${this.addon.state === "startup"}
|
||||
>
|
||||
${this.supervisor.localize("addon.dashboard.start")}
|
||||
</ha-progress-button>
|
||||
`
|
||||
|
@ -672,9 +686,36 @@ class HassioAddonInfo extends LitElement {
|
|||
super.updated(changedProps);
|
||||
if (changedProps.has("addon")) {
|
||||
this._loadData();
|
||||
if (
|
||||
!this._fetchDataTimeout &&
|
||||
this.addon &&
|
||||
"state" in this.addon &&
|
||||
this.addon.state === "startup"
|
||||
) {
|
||||
// Addon is starting up, wait for it to start
|
||||
this._scheduleDataUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _scheduleDataUpdate() {
|
||||
this._fetchDataTimeout = window.setTimeout(async () => {
|
||||
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 async _loadData(): Promise<void> {
|
||||
if ("state" in this.addon && this.addon.state === "started") {
|
||||
this._metrics = await fetchHassioStats(
|
||||
|
|
|
@ -16,6 +16,7 @@ import "../../../src/components/ha-icon-button";
|
|||
import {
|
||||
fetchHassioAddonInfo,
|
||||
HassioAddonDetails,
|
||||
startHassioAddon,
|
||||
} from "../../../src/data/hassio/addon";
|
||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||
import {
|
||||
|
@ -23,7 +24,10 @@ import {
|
|||
validateHassioSession,
|
||||
} from "../../../src/data/hassio/ingress";
|
||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
||||
import {
|
||||
showAlertDialog,
|
||||
showConfirmationDialog,
|
||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||
import "../../../src/layouts/hass-loading-screen";
|
||||
import "../../../src/layouts/hass-subpage";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
|
@ -45,6 +49,8 @@ class HassioIngressView extends LitElement {
|
|||
|
||||
private _sessionKeepAlive?: number;
|
||||
|
||||
private _fetchDataTimeout?: number;
|
||||
|
||||
public disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
|
||||
|
@ -52,16 +58,21 @@ class HassioIngressView extends LitElement {
|
|||
clearInterval(this._sessionKeepAlive);
|
||||
this._sessionKeepAlive = undefined;
|
||||
}
|
||||
if (this._fetchDataTimeout) {
|
||||
clearInterval(this._fetchDataTimeout);
|
||||
this._fetchDataTimeout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._addon) {
|
||||
return html` <hass-loading-screen></hass-loading-screen> `;
|
||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
||||
}
|
||||
|
||||
const iframe = html`<iframe
|
||||
title=${this._addon.name}
|
||||
src=${this._addon.ingress_url!}
|
||||
@load=${this._checkLoaded}
|
||||
>
|
||||
</iframe>`;
|
||||
|
||||
|
@ -132,10 +143,10 @@ class HassioIngressView extends LitElement {
|
|||
return;
|
||||
}
|
||||
|
||||
const addon = this.route.path.substr(1);
|
||||
const addon = this.route.path.substring(1);
|
||||
|
||||
const oldRoute = changedProps.get("route") as this["route"] | undefined;
|
||||
const oldAddon = oldRoute ? oldRoute.path.substr(1) : undefined;
|
||||
const oldAddon = oldRoute ? oldRoute.path.substring(1) : undefined;
|
||||
|
||||
if (addon && addon !== oldAddon) {
|
||||
this._fetchData(addon);
|
||||
|
@ -145,33 +156,23 @@ class HassioIngressView extends LitElement {
|
|||
private async _fetchData(addonSlug: string) {
|
||||
const createSessionPromise = createHassioSession(this.hass);
|
||||
|
||||
let addon;
|
||||
let addon: HassioAddonDetails;
|
||||
|
||||
try {
|
||||
addon = await fetchHassioAddonInfo(this.hass, addonSlug);
|
||||
} catch (err: any) {
|
||||
await showAlertDialog(this, {
|
||||
text: "Unable to fetch add-on info to start Ingress",
|
||||
text: this.supervisor.localize("ingress.error_addon_info"),
|
||||
title: "Supervisor",
|
||||
});
|
||||
await nextRender();
|
||||
history.back();
|
||||
navigate("/hassio/store", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addon.ingress_url) {
|
||||
if (!addon.version) {
|
||||
await showAlertDialog(this, {
|
||||
text: "Add-on does not support Ingress",
|
||||
title: addon.name,
|
||||
});
|
||||
await nextRender();
|
||||
history.back();
|
||||
return;
|
||||
}
|
||||
|
||||
if (addon.state !== "started") {
|
||||
await showAlertDialog(this, {
|
||||
text: "Add-on is not running. Please start it first",
|
||||
text: this.supervisor.localize("ingress.error_addon_not_installed"),
|
||||
title: addon.name,
|
||||
});
|
||||
await nextRender();
|
||||
|
@ -179,13 +180,74 @@ class HassioIngressView extends LitElement {
|
|||
return;
|
||||
}
|
||||
|
||||
let session;
|
||||
if (!addon.ingress_url) {
|
||||
await showAlertDialog(this, {
|
||||
text: this.supervisor.localize("ingress.error_addon_not_supported"),
|
||||
title: addon.name,
|
||||
});
|
||||
await nextRender();
|
||||
history.back();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addon.state || !["startup", "started"].includes(addon.state)) {
|
||||
const confirm = await showConfirmationDialog(this, {
|
||||
text: this.supervisor.localize("ingress.error_addon_not_running"),
|
||||
title: addon.name,
|
||||
confirmText: this.supervisor.localize("ingress.start_addon"),
|
||||
dismissText: this.supervisor.localize("common.no"),
|
||||
});
|
||||
if (confirm) {
|
||||
try {
|
||||
await startHassioAddon(this.hass, addonSlug);
|
||||
fireEvent(this, "supervisor-collection-refresh", {
|
||||
collection: "addon",
|
||||
});
|
||||
this._fetchData(addonSlug);
|
||||
return;
|
||||
} catch (e) {
|
||||
await showAlertDialog(this, {
|
||||
text: this.supervisor.localize("ingress.error_starting_addon"),
|
||||
title: addon.name,
|
||||
});
|
||||
await nextRender();
|
||||
navigate(`/hassio/addon/${addon.slug}/logs`, { replace: true });
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
await nextRender();
|
||||
navigate(`/hassio/addon/${addon.slug}/info`, { replace: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (addon.state === "startup") {
|
||||
// Addon is starting up, wait for it to start
|
||||
this._fetchDataTimeout = window.setTimeout(() => {
|
||||
this._fetchData(addonSlug);
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
if (addon.state !== "started") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._fetchDataTimeout) {
|
||||
clearInterval(this._fetchDataTimeout);
|
||||
this._fetchDataTimeout = undefined;
|
||||
}
|
||||
|
||||
let session: string;
|
||||
|
||||
try {
|
||||
session = await createSessionPromise;
|
||||
} catch (err: any) {
|
||||
if (this._sessionKeepAlive) {
|
||||
clearInterval(this._sessionKeepAlive);
|
||||
}
|
||||
await showAlertDialog(this, {
|
||||
text: "Unable to create an Ingress session",
|
||||
text: this.supervisor.localize("ingress.error_creating_session"),
|
||||
title: addon.name,
|
||||
});
|
||||
await nextRender();
|
||||
|
@ -207,6 +269,31 @@ class HassioIngressView extends LitElement {
|
|||
this._addon = addon;
|
||||
}
|
||||
|
||||
private _checkLoaded(ev): void {
|
||||
if (!this._addon) {
|
||||
return;
|
||||
}
|
||||
if (ev.target.contentDocument.body.textContent === "502: Bad Gateway") {
|
||||
showConfirmationDialog(this, {
|
||||
text: this.supervisor.localize("ingress.error_addon_not_ready"),
|
||||
title: this._addon.name,
|
||||
confirmText: this.supervisor.localize("ingress.retry"),
|
||||
dismissText: this.supervisor.localize("common.no"),
|
||||
confirm: async () => {
|
||||
const addon = this._addon;
|
||||
this._addon = undefined;
|
||||
await Promise.all([
|
||||
this.updateComplete,
|
||||
new Promise((resolve) => {
|
||||
setTimeout(resolve, 500);
|
||||
}),
|
||||
]);
|
||||
this._addon = addon;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _toggleMenu(): void {
|
||||
fireEvent(this, "hass-toggle-menu");
|
||||
}
|
||||
|
|
|
@ -23,7 +23,13 @@ export type AddonStartup =
|
|||
| "services"
|
||||
| "application"
|
||||
| "once";
|
||||
export type AddonState = "started" | "stopped" | null;
|
||||
export type AddonState =
|
||||
| "startup"
|
||||
| "started"
|
||||
| "stopped"
|
||||
| "unknown"
|
||||
| "error"
|
||||
| null;
|
||||
export type AddonRepository = "core" | "local" | string;
|
||||
|
||||
interface AddonTranslations {
|
||||
|
|
|
@ -5834,10 +5834,20 @@
|
|||
"error": "[%key:ui::panel::my::error%]",
|
||||
"error_addon_not_found": "Add-on not found",
|
||||
"error_repository_not_found": "The required repository for this Add-on was not found",
|
||||
"error_addon_not_started": "The requested add-on is not running. Please start it first",
|
||||
"error_addon_not_installed": "The requested add-on is not installed. Please install it first",
|
||||
"error_addon_no_ingress": "The requested add-on does not support ingress"
|
||||
},
|
||||
"ingress": {
|
||||
"error_addon_info": "Unable to fetch add-on info to start Ingress",
|
||||
"error_addon_not_installed": "The add-on is not installed. Please install it first",
|
||||
"error_addon_not_supported": "This add-on does not support Ingress",
|
||||
"error_addon_not_running": "Add-on is not running. Do you want to start it now?",
|
||||
"start_addon": "Start add-on",
|
||||
"error_starting_addon": "Error starting the add-on",
|
||||
"error_creating_session": "Unable to create an Ingress session",
|
||||
"error_addon_not_ready": "The add-on seems to not be ready, it might still be starting. Do you want to try again?",
|
||||
"retry": "Retry"
|
||||
},
|
||||
"system": {
|
||||
"log": {
|
||||
"log_provider": "Log Provider",
|
||||
|
|
Loading…
Reference in New Issue