diff --git a/src/dialogs/more-info/controls/more-info-camera.ts b/src/dialogs/more-info/controls/more-info-camera.ts index d532b5861c..7b339db519 100644 --- a/src/dialogs/more-info/controls/more-info-camera.ts +++ b/src/dialogs/more-info/controls/more-info-camera.ts @@ -4,14 +4,20 @@ import { property, state } from "lit/decorators"; import "../../../components/ha-camera-stream"; import type { CameraEntity } from "../../../data/camera"; import type { HomeAssistant } from "../../../types"; +import "../../../components/buttons/ha-progress-button"; +import { UNAVAILABLE } from "../../../data/entity"; +import { fileDownload } from "../../../util/file_download"; +import { showToast } from "../../../util/toast"; class MoreInfoCamera extends LitElement { - @property({ attribute: false }) public hass?: HomeAssistant; + @property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public stateObj?: CameraEntity; @state() private _attached = false; + @state() private _waiting = false; + public connectedCallback() { super.connectedCallback(); this._attached = true; @@ -23,7 +29,7 @@ class MoreInfoCamera extends LitElement { } protected render() { - if (!this._attached || !this.hass || !this.stateObj) { + if (!this._attached || !this.stateObj) { return nothing; } @@ -34,14 +40,70 @@ class MoreInfoCamera extends LitElement { allow-exoplayer controls > + +
+ + ${this.hass.localize( + "ui.dialogs.more_info_control.camera.download_snapshot" + )} + +
`; } + private async _downloadSnapshot(ev: CustomEvent) { + const button = ev.currentTarget as any; + this._waiting = true; + + try { + const result: Response | undefined = await this.hass.callApiRaw( + "GET", + `camera_proxy/${this.stateObj!.entity_id}` + ); + + if (!result) { + throw new Error("No response from API"); + } + + const blob = await result.blob(); + const url = window.URL.createObjectURL(blob); + fileDownload(url); + } catch (err) { + this._waiting = false; + button.actionError(); + showToast(this, { + message: this.hass.localize( + "ui.dialogs.more_info_control.camera.failed_to_download" + ), + }); + return; + } + + this._waiting = false; + button.actionSuccess(); + } + static get styles(): CSSResultGroup { return css` :host { display: block; } + + .actions { + width: 100%; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-end; + box-sizing: border-box; + padding: 12px; + z-index: 1; + gap: 8px; + } `; } } diff --git a/src/translations/en.json b/src/translations/en.json index d5d68728d1..26c602f546 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1339,6 +1339,10 @@ "button": "[%key:ui::dialogs::more_info_control::cover::switch_mode::button%]", "position": "[%key:ui::dialogs::more_info_control::cover::switch_mode::position%]" } + }, + "camera": { + "download_snapshot": "Download snapshot", + "failed_to_download": "Failed to download snapshot. Please check the logs for more information." } }, "entity_registry": {