From c14425b2d1c8b4a4420cfbb3a7daadc32f75f9d7 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 28 Jul 2025 23:49:08 -0700 Subject: [PATCH] Allow picture card to serve media images (#26291) * Allow picture card to serve media images * small adjustments --- src/data/media_source.ts | 3 ++ src/panels/lovelace/cards/hui-picture-card.ts | 46 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/data/media_source.ts b/src/data/media_source.ts index ec94f3ff89..2015c1f8e7 100644 --- a/src/data/media_source.ts +++ b/src/data/media_source.ts @@ -24,6 +24,9 @@ export const browseLocalMediaPlayer = ( media_content_id: mediaContentId, }); +export const isMediaSourceContentId = (mediaId: string) => + mediaId.startsWith("media-source://"); + export const isLocalMediaSourceContentId = (mediaId: string) => mediaId.startsWith("media-source://media_source"); diff --git a/src/panels/lovelace/cards/hui-picture-card.ts b/src/panels/lovelace/cards/hui-picture-card.ts index ffcb51f84e..c27e12f931 100644 --- a/src/panels/lovelace/cards/hui-picture-card.ts +++ b/src/panels/lovelace/cards/hui-picture-card.ts @@ -18,6 +18,10 @@ import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; import type { PictureCardConfig } from "./types"; import type { PersonEntity } from "../../../data/person"; +import { + isMediaSourceContentId, + resolveMediaSource, +} from "../../../data/media_source"; @customElement("hui-picture-card") export class HuiPictureCard extends LitElement implements LovelaceCard { @@ -37,6 +41,8 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { @state() private _config?: PictureCardConfig; + @state() private _resolvedImage?: string; + public getCardSize(): number { return 5; } @@ -53,7 +59,11 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { } protected shouldUpdate(changedProps: PropertyValues): boolean { - if (!this._config || hasConfigChanged(this, changedProps)) { + if ( + !this._config || + hasConfigChanged(this, changedProps) || + changedProps.has("_resolvedImage") + ) { return true; } if (this._config.image_entity && changedProps.has("hass")) { @@ -70,6 +80,33 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { return false; } + protected willUpdate(changedProps: PropertyValues) { + super.willUpdate(changedProps); + + if (!this._config || !this.hass) { + return; + } + + const firstHass = + changedProps.has("hass") && changedProps.get("hass") === undefined; + const imageChanged = + changedProps.has("_config") && + changedProps.get("_config")?.image !== this._config?.image; + + if ( + (firstHass || imageChanged) && + typeof this._config?.image === "string" && + isMediaSourceContentId(this._config.image) + ) { + this._resolvedImage = undefined; + resolveMediaSource(this.hass, this._config?.image).then((result) => { + this._resolvedImage = result.url; + }); + } else if (imageChanged) { + this._resolvedImage = this._config?.image; + } + } + protected updated(changedProps: PropertyValues): void { super.updated(changedProps); if (!this._config || !this.hass) { @@ -106,7 +143,7 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { } } - let image: string | undefined = this._config.image; + let image: string | undefined = this._resolvedImage; if (this._config.image_entity) { const domain: string = computeDomain(this._config.image_entity); switch (domain) { @@ -121,6 +158,11 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { } } + if (image === undefined) { + // Bail if we're waiting for our image to be resolved from the media-source. + return nothing; + } + return html`