mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Add stream preview element to generic camera (#21463)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
5ccc3365fe
commit
8fa36c8226
@ -181,7 +181,15 @@ class HaHLSPlayer extends LitElement {
|
|||||||
let playlist_url: string;
|
let playlist_url: string;
|
||||||
if (match !== null && matchTwice === null) {
|
if (match !== null && matchTwice === null) {
|
||||||
// Only send the regular playlist url if we match exactly once
|
// Only send the regular playlist url if we match exactly once
|
||||||
playlist_url = new URL(match[3], this._url).href;
|
// In case we arrive here with a relative URL, we need to provide a valid
|
||||||
|
// base/absolute URL to avoid the URL() constructor throwing an error.
|
||||||
|
let base_url: string;
|
||||||
|
try {
|
||||||
|
base_url = new URL(this._url).href;
|
||||||
|
} catch (error) {
|
||||||
|
base_url = new URL(this._url, window.location.href).href;
|
||||||
|
}
|
||||||
|
playlist_url = new URL(match[3], base_url).href;
|
||||||
} else {
|
} else {
|
||||||
playlist_url = this._url;
|
playlist_url = this._url;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
const HAS_CUSTOM_PREVIEW = ["template"];
|
const HAS_CUSTOM_PREVIEW = ["generic_camera", "template"];
|
||||||
|
|
||||||
export interface GenericPreview {
|
export interface GenericPreview {
|
||||||
state: string;
|
state: string;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
import type { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import { LitElement, html } from "lit";
|
import { LitElement, html } from "lit";
|
||||||
|
import type { nothing, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import type { FlowType } from "../../../data/data_entry_flow";
|
import type { FlowType } from "../../../data/data_entry_flow";
|
||||||
import type { GenericPreview } from "../../../data/preview";
|
import type { GenericPreview } from "../../../data/preview";
|
||||||
@ -11,7 +12,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
|
|
||||||
@customElement("flow-preview-generic")
|
@customElement("flow-preview-generic")
|
||||||
class FlowPreviewGeneric extends LitElement {
|
export class FlowPreviewGeneric extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public flowType!: FlowType;
|
@property({ attribute: false }) public flowType!: FlowType;
|
||||||
@ -26,9 +27,9 @@ class FlowPreviewGeneric extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public stepData!: Record<string, any>;
|
@property({ attribute: false }) public stepData!: Record<string, any>;
|
||||||
|
|
||||||
@state() private _preview?: HassEntity;
|
@state() protected _preview?: HassEntity;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() protected _error?: string;
|
||||||
|
|
||||||
private _unsub?: Promise<UnsubscribeFunc>;
|
private _unsub?: Promise<UnsubscribeFunc>;
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ class FlowPreviewGeneric extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render(): TemplateResult | typeof nothing {
|
||||||
if (this._error) {
|
if (this._error) {
|
||||||
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
import { html, nothing } from "lit";
|
||||||
|
import { customElement } from "lit/decorators";
|
||||||
|
import { FlowPreviewGeneric } from "./flow-preview-generic";
|
||||||
|
import "../../../components/ha-hls-player";
|
||||||
|
import "../../../components/ha-circular-progress";
|
||||||
|
|
||||||
|
@customElement("flow-preview-generic_camera")
|
||||||
|
class FlowPreviewGenericCamera extends FlowPreviewGeneric {
|
||||||
|
protected override render() {
|
||||||
|
if (!this._preview) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
if (this._error) {
|
||||||
|
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stillUrl = this._preview.attributes.still_url;
|
||||||
|
const streamUrl = this._preview.attributes.stream_url;
|
||||||
|
|
||||||
|
return html` ${stillUrl
|
||||||
|
? html`<p>Still image:</p>
|
||||||
|
<p>
|
||||||
|
<img src=${stillUrl} alt="Still preview" />
|
||||||
|
</p>`
|
||||||
|
: ""}
|
||||||
|
${streamUrl
|
||||||
|
? html`<p>Stream:</p>
|
||||||
|
<ha-circular-progress
|
||||||
|
class="render-spinner"
|
||||||
|
id="hls-load-spinner"
|
||||||
|
indeterminate
|
||||||
|
size="large"
|
||||||
|
></ha-circular-progress>
|
||||||
|
<ha-hls-player
|
||||||
|
autoplay
|
||||||
|
playsinline
|
||||||
|
.hass=${this.hass}
|
||||||
|
.url=${streamUrl}
|
||||||
|
@load=${this._videoLoaded}
|
||||||
|
></ha-hls-player>`
|
||||||
|
: ""}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _videoLoaded() {
|
||||||
|
this.shadowRoot!.getElementById("hls-load-spinner")?.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"flow-preview-generic_camera": FlowPreviewGenericCamera;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user