Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stream preview element to generic camera #21463

Merged
10 changes: 9 additions & 1 deletion src/components/ha-hls-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,15 @@ class HaHLSPlayer extends LitElement {
let playlist_url: string;
if (match !== null && matchTwice === null) {
// 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 {
playlist_url = this._url;
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/preview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type { HomeAssistant } from "../types";

const HAS_CUSTOM_PREVIEW = ["template"];
const HAS_CUSTOM_PREVIEW = ["generic_camera", "template"];

export interface GenericPreview {
state: string;
Expand Down
9 changes: 5 additions & 4 deletions src/dialogs/config-flow/previews/flow-preview-generic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
import { LitElement, html } from "lit";
import type { nothing, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import type { FlowType } from "../../../data/data_entry_flow";
import type { GenericPreview } from "../../../data/preview";
Expand All @@ -11,7 +12,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-alert";

@customElement("flow-preview-generic")
class FlowPreviewGeneric extends LitElement {
export class FlowPreviewGeneric extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property() public flowType!: FlowType;
Expand All @@ -26,9 +27,9 @@ class FlowPreviewGeneric extends LitElement {

@property() 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>;

Expand All @@ -46,7 +47,7 @@ class FlowPreviewGeneric extends LitElement {
}
}

protected render() {
protected render(): TemplateResult | typeof nothing {
if (this._error) {
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
}
Expand Down
53 changes: 53 additions & 0 deletions src/dialogs/config-flow/previews/flow-preview-generic_camera.ts
Original file line number Diff line number Diff line change
@@ -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) {
davet2001 marked this conversation as resolved.
Show resolved Hide resolved
davet2001 marked this conversation as resolved.
Show resolved Hide resolved
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}
bramkragten marked this conversation as resolved.
Show resolved Hide resolved
@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