From 6e4fc7c827156211137fe5a00999c1b8a2e6c188 Mon Sep 17 00:00:00 2001 From: piitaya Date: Fri, 15 Apr 2022 10:10:11 +0200 Subject: [PATCH 1/2] feat(media-player): add options to show media info instead of name/state --- .../media-player-card-config.ts | 4 +- .../media-player-card-editor.ts | 7 ++- .../media-player-card/media-player-card.ts | 8 +-- src/cards/media-player-card/utils.ts | 58 +++++++++++-------- src/translations/en.json | 1 + src/translations/fr.json | 1 + 6 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/cards/media-player-card/media-player-card-config.ts b/src/cards/media-player-card/media-player-card-config.ts index 42c8f57d6..ad5be9c73 100644 --- a/src/cards/media-player-card/media-player-card-config.ts +++ b/src/cards/media-player-card/media-player-card-config.ts @@ -1,5 +1,5 @@ import { ActionConfig, LovelaceCardConfig } from "custom-card-helpers"; -import { array, assign, enums, object, optional, string } from "superstruct"; +import { array, assign, boolean, enums, object, optional, string } from "superstruct"; import { actionConfigStruct } from "../../utils/action-struct"; import { baseLovelaceCardConfig } from "../../utils/editor-styles"; import { Layout, layoutStruct } from "../../utils/layout"; @@ -27,6 +27,7 @@ export interface MediaPlayerCardConfig extends LovelaceCardConfig { entity?: string; name?: string; icon?: string; + show_media_info?: boolean; volume_controls?: MediaPlayerVolumeControl[]; media_controls?: MediaPlayerMediaControl[]; layout?: Layout; @@ -41,6 +42,7 @@ export const mediaPlayerCardConfigStruct = assign( entity: optional(string()), icon: optional(string()), name: optional(string()), + show_media_info: optional(boolean()), volume_controls: optional(array(enums(MEDIA_PLAYER_VOLUME_CONTROLS))), media_controls: optional(array(enums(MEDIA_LAYER_MEDIA_CONTROLS))), layout: optional(layoutStruct), diff --git a/src/cards/media-player-card/media-player-card-editor.ts b/src/cards/media-player-card/media-player-card-editor.ts index 41343aea8..03e834cdf 100644 --- a/src/cards/media-player-card/media-player-card-editor.ts +++ b/src/cards/media-player-card/media-player-card-editor.ts @@ -17,7 +17,7 @@ import { MEDIA_PLAYER_VOLUME_CONTROLS, } from "./media-player-card-config"; -export const MEDIA_FIELDS = ["media_controls", "volume_controls"]; +export const MEDIA_FIELDS = ["show_media_info", "media_controls", "volume_controls"]; const computeSchema = memoizeOne((localize: LocalizeFunc, icon?: string): HaFormSchema[] => [ { name: "entity", selector: { entity: { domain: MEDIA_PLAYER_ENTITY_DOMAINS } } }, @@ -32,6 +32,11 @@ const computeSchema = memoizeOne((localize: LocalizeFunc, icon?: string): HaForm name: "", schema: [{ name: "layout", selector: { "mush-layout": {} } }], }, + { + type: "grid", + name: "", + schema: [{ name: "show_media_info", selector: { boolean: {} } }], + }, { type: "grid", name: "", diff --git a/src/cards/media-player-card/media-player-card.ts b/src/cards/media-player-card/media-player-card.ts index 45e334126..b8e91e23e 100644 --- a/src/cards/media-player-card/media-player-card.ts +++ b/src/cards/media-player-card/media-player-card.ts @@ -26,7 +26,7 @@ import { isMediaControlVisible } from "./controls/media-player-media-control"; import "./controls/media-player-volume-control"; import { isVolumeControlVisible } from "./controls/media-player-volume-control"; import { MediaPlayerCardConfig } from "./media-player-card-config"; -import { computeIcon, getCardName, getStateDisplay } from "./utils"; +import { computeMediaIcon, computeMediaNameDisplay, computeMediaStateDisplay } from "./utils"; type MediaPlayerCardControl = "media_control" | "volume_control"; @@ -135,14 +135,14 @@ export class MediaPlayerCard extends LitElement implements LovelaceCard { const entity_id = this._config.entity; const entity = this.hass.states[entity_id] as MediaPlayerEntity; - const icon = computeIcon(this._config, entity); + const icon = computeMediaIcon(this._config, entity); const layout = getLayoutFromConfig(this._config); const active = isActive(entity); let iconStyle = {}; - let nameDisplay = getCardName(this._config, entity); - let stateDisplay = getStateDisplay(entity, this.hass); + let nameDisplay = computeMediaNameDisplay(this._config, entity); + let stateDisplay = computeMediaStateDisplay(this._config, entity, this.hass); const rtl = computeRTL(this.hass); diff --git a/src/cards/media-player-card/utils.ts b/src/cards/media-player-card/utils.ts index bf956d830..09f39c342 100644 --- a/src/cards/media-player-card/utils.ts +++ b/src/cards/media-player-card/utils.ts @@ -30,9 +30,12 @@ export function callService( }); } -export function getCardName(config: MediaPlayerCardConfig, entity: MediaPlayerEntity): string { +export function computeMediaNameDisplay( + config: MediaPlayerCardConfig, + entity: MediaPlayerEntity +): string { let name = config.name || entity.attributes.friendly_name || ""; - if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state)) { + if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state) && config.show_media_info) { if (entity.attributes.media_title) { name = entity.attributes.media_title; } @@ -40,9 +43,13 @@ export function getCardName(config: MediaPlayerCardConfig, entity: MediaPlayerEn return name; } -export function getStateDisplay(entity: MediaPlayerEntity, hass: HomeAssistant): string { +export function computeMediaStateDisplay( + config: MediaPlayerCardConfig, + entity: MediaPlayerEntity, + hass: HomeAssistant +): string { let state = computeStateDisplay(hass.localize, entity, hass.locale); - if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state)) { + if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state) && config.show_media_info) { return computeMediaDescription(entity) || state; } return state; @@ -54,30 +61,31 @@ export function getVolumeLevel(entity: MediaPlayerEntity) { : undefined; } -export function computeIcon(config: MediaPlayerCardConfig, entity: MediaPlayerEntity): string { +export function computeMediaIcon(config: MediaPlayerCardConfig, entity: MediaPlayerEntity): string { var icon = config.icon || stateIcon(entity); - if (!entity.attributes.app_name) return icon; - - var app = entity.attributes.app_name.toLowerCase(); - switch (app) { - case "spotify": - return "mdi:spotify"; - case "google podcasts": - return "mdi:google-podcast"; - case "plex": - return "mdi:plex"; - case "soundcloud": - return "mdi:soundcloud"; - case "youtube": - return "mdi:youtube"; - case "oto music": - return "mdi:music-circle"; - case "netflix": - return "mdi:netflix"; - default: - return icon; + if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state) && config.show_media_info) { + var app = entity.attributes.app_name?.toLowerCase(); + switch (app) { + case "spotify": + return "mdi:spotify"; + case "google podcasts": + return "mdi:google-podcast"; + case "plex": + return "mdi:plex"; + case "soundcloud": + return "mdi:soundcloud"; + case "youtube": + return "mdi:youtube"; + case "oto music": + return "mdi:music-circle"; + case "netflix": + return "mdi:netflix"; + default: + return icon; + } } + return icon; } export interface ControlButton { diff --git a/src/translations/en.json b/src/translations/en.json index 4c24519f0..8abe07ecb 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -89,6 +89,7 @@ "commands": "Commands" }, "media-player": { + "show_media_info": "Show media info", "media_controls": "Media controls", "media_controls_list": { "on_off": "Turn on/off", diff --git a/src/translations/fr.json b/src/translations/fr.json index 99f58b16d..c878737ed 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -89,6 +89,7 @@ "commands": "Commandes" }, "media-player": { + "show_media_info": "Montrer les informations sur le media", "media_controls": "Contrôles du media", "media_controls_list": { "on_off": "Allumer/Éteindre", From f2d2b16df72e96c8137d2651bf063d1b3428c68e Mon Sep 17 00:00:00 2001 From: piitaya Date: Fri, 15 Apr 2022 10:21:13 +0200 Subject: [PATCH 2/2] feat(media-player): add options to use media artwork instead of icon --- .../media-player-card-config.ts | 2 ++ .../media-player-card-editor.ts | 12 +++++-- .../media-player-card/media-player-card.ts | 31 +++++++++++++------ src/translations/en.json | 1 + src/translations/fr.json | 1 + 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/cards/media-player-card/media-player-card-config.ts b/src/cards/media-player-card/media-player-card-config.ts index ad5be9c73..19876fafa 100644 --- a/src/cards/media-player-card/media-player-card-config.ts +++ b/src/cards/media-player-card/media-player-card-config.ts @@ -28,6 +28,7 @@ export interface MediaPlayerCardConfig extends LovelaceCardConfig { name?: string; icon?: string; show_media_info?: boolean; + use_media_artwork?: boolean; volume_controls?: MediaPlayerVolumeControl[]; media_controls?: MediaPlayerMediaControl[]; layout?: Layout; @@ -43,6 +44,7 @@ export const mediaPlayerCardConfigStruct = assign( icon: optional(string()), name: optional(string()), show_media_info: optional(boolean()), + use_media_artwork: optional(boolean()), volume_controls: optional(array(enums(MEDIA_PLAYER_VOLUME_CONTROLS))), media_controls: optional(array(enums(MEDIA_LAYER_MEDIA_CONTROLS))), layout: optional(layoutStruct), diff --git a/src/cards/media-player-card/media-player-card-editor.ts b/src/cards/media-player-card/media-player-card-editor.ts index 03e834cdf..1e78cfd3c 100644 --- a/src/cards/media-player-card/media-player-card-editor.ts +++ b/src/cards/media-player-card/media-player-card-editor.ts @@ -17,7 +17,12 @@ import { MEDIA_PLAYER_VOLUME_CONTROLS, } from "./media-player-card-config"; -export const MEDIA_FIELDS = ["show_media_info", "media_controls", "volume_controls"]; +export const MEDIA_FIELDS = [ + "show_media_info", + "use_media_artwork", + "media_controls", + "volume_controls", +]; const computeSchema = memoizeOne((localize: LocalizeFunc, icon?: string): HaFormSchema[] => [ { name: "entity", selector: { entity: { domain: MEDIA_PLAYER_ENTITY_DOMAINS } } }, @@ -35,7 +40,10 @@ const computeSchema = memoizeOne((localize: LocalizeFunc, icon?: string): HaForm { type: "grid", name: "", - schema: [{ name: "show_media_info", selector: { boolean: {} } }], + schema: [ + { name: "show_media_info", selector: { boolean: {} } }, + { name: "use_media_artwork", selector: { boolean: {} } }, + ], }, { type: "grid", diff --git a/src/cards/media-player-card/media-player-card.ts b/src/cards/media-player-card/media-player-card.ts index b8e91e23e..2b640d9a4 100644 --- a/src/cards/media-player-card/media-player-card.ts +++ b/src/cards/media-player-card/media-player-card.ts @@ -27,6 +27,10 @@ import "./controls/media-player-volume-control"; import { isVolumeControlVisible } from "./controls/media-player-volume-control"; import { MediaPlayerCardConfig } from "./media-player-card-config"; import { computeMediaIcon, computeMediaNameDisplay, computeMediaStateDisplay } from "./utils"; +import "../../shared/badge-icon"; +import "../../shared/card"; +import "../../shared/shape-avatar"; +import "../../shared/shape-icon"; type MediaPlayerCardControl = "media_control" | "volume_control"; @@ -137,15 +141,16 @@ export class MediaPlayerCard extends LitElement implements LovelaceCard { const icon = computeMediaIcon(this._config, entity); const layout = getLayoutFromConfig(this._config); - const active = isActive(entity); - - let iconStyle = {}; let nameDisplay = computeMediaNameDisplay(this._config, entity); let stateDisplay = computeMediaStateDisplay(this._config, entity, this.hass); const rtl = computeRTL(this.hass); + const artwork = this._config.use_media_artwork + ? entity.attributes.entity_picture + : undefined; + return html` - + ${artwork + ? html` + + ` + : html` + + `} ${entity.state === "unavailable" ? html`