diff --git a/src/components/ha-file-upload.ts b/src/components/ha-file-upload.ts index 3d3749c8b4..785e67ca32 100644 --- a/src/components/ha-file-upload.ts +++ b/src/components/ha-file-upload.ts @@ -86,11 +86,12 @@ export class HaFileUpload extends LitElement { ? html`
${this.uploadingLabel || this.value + >${this.uploadingLabel || + (this.value ? localize("ui.components.file-upload.uploading_name", { name: this._name, }) - : localize("ui.components.file-upload.uploading")} ${this.progress ? html`
diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts index 78caa83cd0..d7c357f802 100644 --- a/src/data/zwave_js.ts +++ b/src/data/zwave_js.ts @@ -925,7 +925,8 @@ export const uploadFirmwareAndBeginUpdate = async ( hass: HomeAssistant, device_id: string, file: File, - target?: number + target?: number, + signal?: AbortSignal ) => { const fd = new FormData(); fd.append("file", file); @@ -937,6 +938,7 @@ export const uploadFirmwareAndBeginUpdate = async ( { method: "POST", body: fd, + signal, } ); diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts index cf068f7ec5..3076fcb32d 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts @@ -77,6 +77,8 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { private _deviceName?: string; + private _cancelUpload?: () => void; + public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void { this._deviceName = computeDeviceNameDisplay(params.device, this.hass!); this.device = params.device; @@ -114,12 +116,16 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { .label=${this.hass.localize( "ui.panel.config.zwave_js.update_firmware.upload_firmware" )} + .uploadingLabel=${this.hass.localize( + "ui.panel.config.zwave_js.update_firmware.uploading", + { name: this._firmwareFile?.name } + )} .value=${this._firmwareFile} @file-picked=${this._uploadFile} > ${this._nodeStatus.is_controller_node ? nothing - : html`

+ : html`

${this.hass.localize( "ui.panel.config.zwave_js.update_firmware.firmware_target_intro" )} @@ -129,11 +135,12 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { .data=${{ firmware_target: this._firmwareTarget }} .schema=${firmwareTargetSchema} @value-changed=${this._firmwareTargetChanged} + .disabled=${this._uploading} >`} ${this.hass.localize( "ui.panel.config.zwave_js.update_firmware.begin_update" @@ -182,7 +189,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { ${!this._updateProgressMessage && !this._updateFinishedMessage ? !this._updateInProgress ? html` -

+

${this.hass.localize( `ui.panel.config.zwave_js.update_firmware.introduction${localizationKeySuffix}`, { @@ -191,6 +198,15 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { )}

${beginFirmwareUpdateHTML} + ${this._uploading && + this._nodeStatus.status === NodeStatus.Asleep + ? html`

+ ${this.hass.localize( + "ui.panel.config.zwave_js.update_firmware.device_asleep" + )} +

` + : nothing} + ${this._uploading ? abortFirmwareUpdateButton : nothing} ` : html`

@@ -316,17 +332,26 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { this._updateProgressMessage = this._updateFinishedMessage = undefined; try { this._subscribeNodeFirmwareUpdate(); - await uploadFirmwareAndBeginUpdate( - this.hass, - this.device!.id, - this._firmwareFile!, - this._firmwareTarget - ); + await new Promise((resolve, reject) => { + const abortController = new AbortController(); + this._cancelUpload = () => { + this._cancelUpload = undefined; + abortController.abort(); + resolve(); + }; + uploadFirmwareAndBeginUpdate( + this.hass, + this.device!.id, + this._firmwareFile!, + this._firmwareTarget, + abortController.signal + ) + .then(() => this._cancelUpload?.()) + .catch(reject); + }); this._updateInProgress = true; - this._uploading = false; } catch (err: any) { this._unsubscribeNodeFirmwareUpdate(); - this._uploading = false; showAlertDialog(this, { title: this.hass.localize( "ui.panel.config.zwave_js.update_firmware.upload_failed" @@ -334,6 +359,8 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { text: err.message, confirmText: this.hass!.localize("ui.common.close"), }); + } finally { + this._uploading = false; } } @@ -350,6 +377,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { confirmText: this.hass!.localize("ui.common.yes"), }) ) { + this._cancelUpload?.(); this._unsubscribeNodeFirmwareUpdate(); try { await abortZwaveNodeFirmwareUpdate(this.hass, this.device!.id); @@ -366,6 +394,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { this._updateFinishedMessage = undefined; this._updateProgressMessage = undefined; this._updateInProgress = false; + this._uploading = false; } } @@ -455,6 +484,17 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { width: 68px; height: 48px; } + + p.disabled { + color: var(--disabled-text-color); + } + + p.wakeup { + color: var(--warning-color); + font-weight: var(--ha-font-weight-bold); + margin-top: 24px; + margin-bottom: 0; + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index b703e2816e..4465f0fd6e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6284,6 +6284,8 @@ "introduction_controller": "Select the firmware file you would like to use to update {device}. Note that once you start a firmware update, you MUST wait for the update to complete.", "firmware_target_intro": "Select the firmware target (0 for the Z-Wave chip, ≥1 for other chips if they exist) for this update.", "firmware_target": "Firmware target (chip)", + "uploading": "Uploading {name}. Please do not close this dialog.", + "device_asleep": "The device is asleep. Wake the device to start the update.", "upload_firmware": "Upload firmware", "upload_failed": "Upload failed", "begin_update": "Begin firmware update",