diff --git a/src/components/ha-hls-player.ts b/src/components/ha-hls-player.ts index cf3ed5a526a1..d81b54013599 100644 --- a/src/components/ha-hls-player.ts +++ b/src/components/ha-hls-player.ts @@ -150,7 +150,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[2], 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[2], base_url).href; } else { playlist_url = this.url; } diff --git a/src/data/preview.ts b/src/data/preview.ts index 1c3a24c7779f..783d351f366e 100644 --- a/src/data/preview.ts +++ b/src/data/preview.ts @@ -1,7 +1,7 @@ import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { HomeAssistant } from "../types"; -const HAS_CUSTOM_PREVIEW = ["template"]; +const HAS_CUSTOM_PREVIEW = ["generic_camera", "template"]; export interface GenericPreview { state: string; diff --git a/src/dialogs/config-flow/previews/flow-preview-generic.ts b/src/dialogs/config-flow/previews/flow-preview-generic.ts index 78209ce3101a..a149dcbc5d43 100644 --- a/src/dialogs/config-flow/previews/flow-preview-generic.ts +++ b/src/dialogs/config-flow/previews/flow-preview-generic.ts @@ -9,7 +9,7 @@ import { debounce } from "../../../common/util/debounce"; import { fireEvent } from "../../../common/dom/fire_event"; @customElement("flow-preview-generic") -class FlowPreviewGeneric extends LitElement { +export class FlowPreviewGeneric extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public flowType!: FlowType; @@ -24,7 +24,7 @@ class FlowPreviewGeneric extends LitElement { @property() public stepData!: Record; - @state() private _preview?: HassEntity; + @state() protected _preview?: HassEntity; @state() private _error?: string; diff --git a/src/dialogs/config-flow/previews/flow-preview-generic_camera.ts b/src/dialogs/config-flow/previews/flow-preview-generic_camera.ts new file mode 100644 index 000000000000..df99f9c2072f --- /dev/null +++ b/src/dialogs/config-flow/previews/flow-preview-generic_camera.ts @@ -0,0 +1,38 @@ +import { html, nothing } from "lit"; +import { customElement } from "lit/decorators"; +import { FlowPreviewGeneric } from "./flow-preview-generic"; + +@customElement("flow-preview-generic_camera") +class FlowPreviewGenericCamera extends FlowPreviewGeneric { + protected override render() { + if (!this._preview) { + return nothing; + } + + const stillUrl = this._preview.attributes.stillUrl; + const streamUrl = this._preview.attributes.streamUrl; + + return html` ${stillUrl + ? html`

Still image:

+

+ Still preview +

` + : ""} + ${streamUrl + ? html`

Stream:

+ ` + : ""}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + "flow-preview-generic_camera": FlowPreviewGenericCamera; + } +}