From 2a3483d204fa0107b1eaefab282e6423a5f7996e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Fri, 19 Jul 2024 10:36:14 +0200 Subject: [PATCH] Implement a new version/pre-release selector (#762) * Implement a new version/pre-release selector * cleanup --- .../dialogs/hacs-download-dialog.ts | 201 +++++++++++++++--- src/data/repository.ts | 8 + src/localize/languages/en.json | 9 +- 3 files changed, 186 insertions(+), 32 deletions(-) diff --git a/src/components/dialogs/hacs-download-dialog.ts b/src/components/dialogs/hacs-download-dialog.ts index d82fbb56..d7a0f344 100644 --- a/src/components/dialogs/hacs-download-dialog.ts +++ b/src/components/dialogs/hacs-download-dialog.ts @@ -8,8 +8,13 @@ import { mainWindow } from "../../../homeassistant-frontend/src/common/dom/get_m import { computeRTL } from "../../../homeassistant-frontend/src/common/util/compute_rtl"; import "../../../homeassistant-frontend/src/components/ha-alert"; import "../../../homeassistant-frontend/src/components/ha-button"; +import "../../../homeassistant-frontend/src/components/ha-circular-progress"; import "../../../homeassistant-frontend/src/components/ha-dialog"; +import "../../../homeassistant-frontend/src/components/ha-expansion-panel"; import "../../../homeassistant-frontend/src/components/ha-form/ha-form"; +import "../../../homeassistant-frontend/src/components/ha-list-item"; + +import { relativeTime } from "../../../homeassistant-frontend/src/common/datetime/relative_time"; import { showConfirmationDialog } from "../../../homeassistant-frontend/src/dialogs/generic/show-dialog-box"; import type { HomeAssistant } from "../../../homeassistant-frontend/src/types"; import { HacsDispatchEvent } from "../../data/common"; @@ -18,12 +23,61 @@ import { RepositoryBase, repositoryDownloadVersion, RepositoryInfo, + repositoryReleases, } from "../../data/repository"; import { websocketSubscription } from "../../data/websocket"; import { HacsStyles } from "../../styles/hacs-common-style"; import { generateFrontendResourceURL } from "../../tools/frontend-resource"; import type { HacsDownloadDialogParams } from "./show-hacs-dialog"; +@customElement("release-item") +export class ReleaseItem extends LitElement { + @property({ attribute: false }) public locale!: HomeAssistant["locale"]; + @property({ attribute: false }) public release!: { + tag: string; + published_at: string; + name: string; + prerelease: boolean; + }; + + protected render() { + return html` + + ${this.release.tag} + ${this.release.prerelease ? html`pre-release` : nothing} + + + ${relativeTime(new Date(this.release.published_at), this.locale)} + ${this.release.name && this.release.name !== this.release.tag + ? html` - ${this.release.name}` + : nothing} + + `; + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: flex; + flex-direction: column; + } + .secondary { + font-size: 0.8em; + color: var(--secondary-text-color); + font-style: italic; + } + .pre-release { + background-color: var(--accent-color); + padding: 2px 4px; + font-size: 0.8em; + font-weight: 600; + border-radius: 12px; + margin: 0 2px; + color: var(--secondary-background-color); + } + `; + } +} @customElement("hacs-download-dialog") export class HacsDonwloadDialog extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -34,6 +88,13 @@ export class HacsDonwloadDialog extends LitElement { @state() private _error?: any; + @state() private _releases?: { + tag: string; + name: string; + published_at: string; + prerelease: boolean; + }[]; + @state() public _repository?: RepositoryInfo; @state() _dialogParams?: HacsDownloadDialogParams; @@ -52,6 +113,7 @@ export class HacsDonwloadDialog extends LitElement { if (this._repository && this._repository.version_or_commit !== "commit") { this._selectedVersion = this._repository.available_version; } + this._releases = undefined; websocketSubscription( this.hass, @@ -70,6 +132,8 @@ export class HacsDonwloadDialog extends LitElement { this._error = undefined; this._installing = false; this._waiting = false; + this._releases = undefined; + this._selectedVersion = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -82,16 +146,35 @@ export class HacsDonwloadDialog extends LitElement { }); private async _fetchRepository() { - this._repository = await fetchRepositoryInformation( - this.hass, - this._dialogParams!.repositoryId, - ); + try { + this._repository = await fetchRepositoryInformation( + this.hass, + this._dialogParams!.repositoryId, + ); + } catch (err: any) { + this._error = err; + } } protected render() { - if (!this._dialogParams || !this._repository) { + if (!this._dialogParams) { return nothing; } + if (!this._repository) { + return html` + +
+ + ${this._error + ? html` + ${this._error.message || this._error} + ` + : nothing} +
+
+ `; + } + const installPath = this._getInstallPath(this._repository); return html`
- ${!this._repository.can_download - ? html` - ${this._dialogParams.hacs.localize("confirm.home_assistant_version_not_correct", { - haversion: this.hass.config.version, - minversion: this._repository.homeassistant, - })} - ` - : ""} +

+ ${this._dialogParams.hacs.localize( + this._repository.version_or_commit === "commit" + ? "dialog_download.will_download_commit" + : "dialog_download.will_download_version", + { + ref: html` + ${this._selectedVersion || this._repository.available_version} + `, + }, + )} +

${this._dialogParams.hacs.localize("dialog_download.note_downloaded", { location: html`'${installPath}'`, @@ -118,7 +205,7 @@ export class HacsDonwloadDialog extends LitElement { this._dialogParams.hacs.info.lovelace_mode !== "storage" ? html`

${this._dialogParams.hacs.localize(`dialog_download.lovelace_instruction`)}

-
+                  
                 url: ${generateFrontendResourceURL({ repository: this._repository })}
                 type: module
                 
${this._dialogParams.hacs.localize("dialog_download.restart")}

` : nothing}
- ${this._error?.message + ${this._selectedVersion + ? html` +

${this._dialogParams!.hacs.localize("dialog_download.release_warning")}

+ ${this._releases === undefined + ? this._dialogParams.hacs.localize("dialog_download.fetching_releases") + : this._releases.length === 0 + ? this._dialogParams.hacs.localize("dialog_download.no_releases") + : html` ({ + value: release.tag, + label: html` + ${release.tag} + `, + })), + }, + }, + }, + ]} + >`} +
` + : nothing} + ${this._error ? html` - ${this._error.message} + ${this._error.message || this._error} ` : nothing} ${this._installing @@ -143,7 +265,7 @@ export class HacsDonwloadDialog extends LitElement { ${this._dialogParams.hacs.localize("common.download")} @@ -152,6 +274,11 @@ export class HacsDonwloadDialog extends LitElement { `; } + private _computeLabel = (entry: any): string => + entry.name === "release" + ? this._dialogParams!.hacs.localize("dialog_download.release") + : entry.name; + private async _installRepository(): Promise { if (!this._repository) { return; @@ -167,11 +294,6 @@ export class HacsDonwloadDialog extends LitElement { return; } - if (!this._repository.can_download) { - this._error = "Can not download this repository."; - return; - } - this._installing = true; this._error = undefined; @@ -179,9 +301,7 @@ export class HacsDonwloadDialog extends LitElement { await repositoryDownloadVersion( this.hass, String(this._repository.id), - this._repository?.version_or_commit !== "commit" - ? this._repository.available_version - : undefined, + this._selectedVersion || this._repository.available_version, ); } catch (err: any) { this._error = err || { @@ -216,6 +336,21 @@ export class HacsDonwloadDialog extends LitElement { } } + async _fetchReleases() { + if (this._releases !== undefined) { + return; + } + try { + this._releases = await repositoryReleases(this.hass, this._repository!.id); + } catch (error) { + this._error = error; + } + } + + private _versionChanged(ev: CustomEvent) { + this._selectedVersion = ev.detail.value.release; + } + static get styles(): CSSResultGroup { return [ HacsStyles, @@ -223,20 +358,23 @@ export class HacsDonwloadDialog extends LitElement { .note { margin-top: 12px; } - .lovelace { - margin-top: 8px; - } - .learn_more { - color: var(--hcv-text-color-primary); - } pre { white-space: pre-line; user-select: all; + padding: 8px; } mwc-linear-progress { margin-bottom: -8px; margin-top: 4px; } + ha-expansion-panel { + background-color: var(--secondary-background-color); + padding: 8px; + } + .loading { + text-align: center; + padding: 16px; + } `, ]; } @@ -245,5 +383,6 @@ export class HacsDonwloadDialog extends LitElement { declare global { interface HTMLElementTagNameMap { "hacs-download-dialog": HacsDonwloadDialog; + "release-item": ReleaseItem; } } diff --git a/src/data/repository.ts b/src/data/repository.ts index a7008dc0..e83acd2a 100644 --- a/src/data/repository.ts +++ b/src/data/repository.ts @@ -68,3 +68,11 @@ export const repositoryDownloadVersion = async ( repository: repository, version, }); + +export const repositoryReleases = async (hass: HomeAssistant, repositoryId: string) => + hass.connection.sendMessagePromise< + { tag: string; name: string; published_at: string; prerelease: boolean }[] + >({ + type: "hacs/repository/releases", + repository_id: repositoryId, + }); diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index fe460817..b90ac373 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -75,6 +75,13 @@ "dialog_download": { "type": "Type", "url": "URL", + "will_download_version": "Version {ref} will be downloaded", + "will_download_commit": "Commit {ref} will be downloaded", + "different_version": "Need a different version?", + "fetching_releases": "Fetching releases...", + "no_releases": "No releases found", + "release": "Release", + "release_warning": "It is not advised to use this section to do a rollback, restore a backup instead.", "restart": "Remember that you need to restart Home Assistant before changes to integrations (custom_components) are applied.", "selector_note": "The version selector will be removed in a future release. If you need to install a specific version, you can do so by using the service call for update entities.", "note_downloaded": "When downloaded, this will be located in {location}", @@ -165,4 +172,4 @@ } } } -} \ No newline at end of file +}