diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c7eb78..7504553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Change are listed in reverse chronological order (newest to oldest). +###### [ 1.0.1 ] - 2024/05/12 + + * Removed `console.log` messages that were being used for testing. + ###### [ 1.0.0 ] - 2024/05/10 * Version 1 initial release. diff --git a/README.md b/README.md index 12cc2df..3f2f07a 100644 --- a/README.md +++ b/README.md @@ -22,24 +22,27 @@ Check out the [Configuration Guide wiki](https://github.com/thlucas1/homeassista Here's a quick look on what the card looks like. _Pandora Stations, Panel Mode_ - + _SoundTouch Presets, Panel Mode_ - + -_Editor UI, SoundTouch Presets_ - +_SoundTouch Recently Played, Panel Mode_ + + +_Editor UI, General Options_ + ## HACS Installation Instructions (recommended) -- on your sidebar go to HACS > Frontend -- click on the 3-dot overflow menu in the upper right, and select `custom repositories` item. -- copy / paste `https://github.com/thlucas1/homeassistantcomponent_soundtouchplus_card` in the Repository textbox and select `Lovelace` for the category entry. -- click on `Add` to add the custom repository. -- you can then click on the `SoundTouchPlus Card` repository entry (you may need to filter your list first to find the new entry). -- click on `download` to start the download. It will install the card to your config/custom_components directory. -- go back on your dashboard and click on the icon at the right top corner then on Edit dashboard. -- you can now click on Add card in the bottom right corner and search for "Custom: SoundTouchPlus Card". +- On your Home Assistant sidebar menu, go to HACS > Frontend +- Click on the 3-dot overflow menu in the upper right, and select `custom repositories` item. +- Copy / paste `https://github.com/thlucas1/homeassistantcomponent_soundtouchplus_card` in the Repository textbox and select `Lovelace` for the category entry. +- Click on `Add` to add the custom repository. +- You can then click on the `SoundTouchPlus Card` repository entry (you may need to filter your list first to find the new entry). +- Click on `download` to start the download. It will install the card to your `/config/www/community/homeassistantcomponent_soundtouchplus_card` directory. +- Go back on your dashboard and click on the icon at the right top corner then on Edit dashboard. +- You can now click on Add card in the bottom right corner and search for "Custom: SoundTouchPlus Card". ## Manual Installation diff --git a/SoundTouchPlusCard.njsproj b/SoundTouchPlusCard.njsproj index d689ec3..e829050 100644 --- a/SoundTouchPlusCard.njsproj +++ b/SoundTouchPlusCard.njsproj @@ -5,7 +5,7 @@ 2.0 {19dfee94-5cae-417c-ac13-38b165e4121e} . - ShowAllFiles + ProjectFiles dist\soundtouchplus-card.js . . diff --git a/src/card.ts b/src/card.ts index 2597e46..a824420 100644 --- a/src/card.ts +++ b/src/card.ts @@ -14,7 +14,7 @@ import { Section } from './types/section' import './components/footer'; import './editor/editor'; import { PROGRESS_DONE, PROGRESS_STARTED, SECTION_SELECTED } from './constants'; -import { formatPlayerInfo, removeSpecialChars } from './utils/media-browser-utils'; +import { formatTitleInfo, removeSpecialChars } from './utils/media-browser-utils'; import { isNumber } from './utils/utils'; //const LOGPFX = "STPC - card." @@ -94,11 +94,13 @@ export class Card extends LitElement { // has not been set set. this.createStore(); + // TODO - add a check to see if the player is of integration type 'soundtouchplus'. + // calculate height of the card, accounting for any extra // titles that are shown, footer, etc. const sections = this.config.sections; const showFooter = !sections || sections.length > 1; - const title = formatPlayerInfo(this.store.player, this.config.title); + const title = formatTitleInfo(this.config.title, this.config, this.store.player); //console.log(LOGPFX + "render():\n this.section=%s", JSON.stringify(this.section)) diff --git a/src/editor/base-editor.ts b/src/editor/base-editor.ts index 58b4052..1df1857 100644 --- a/src/editor/base-editor.ts +++ b/src/editor/base-editor.ts @@ -99,7 +99,7 @@ export abstract class BaseEditor extends LitElement { // // is this the first render? if so, then refresh the list. // if (this.sourceListLastUpdatedOn == 1) { - // console.log("base-editor.createStore() calling updateSourceList()"); + // //console.log("base-editor.createStore() calling updateSourceList()"); // this.updateSourceList(this.player); // } } @@ -144,7 +144,7 @@ export abstract class BaseEditor extends LitElement { //protected configChanged() { - // console.log("base-editor.configChanged() - configuration has changed"); + // //console.log("base-editor.configChanged() - configuration has changed"); // fireEvent(this, 'config-changed', { config: this.config }); // this.requestUpdate(); //} @@ -162,7 +162,7 @@ export abstract class BaseEditor extends LitElement { // */ //private updateSourceList(player: MediaPlayer): void { - // console.log("base-editor.updateSourceList() - player object:\n%s", JSON.stringify(player,null,2)); + // //console.log("base-editor.updateSourceList() - player object:\n%s", JSON.stringify(player,null,2)); // // update the media list; we will force the `sourceListLastUpdatedOn` attribute // // with the current epoch date (in seconds) so that the refresh is only triggered once. @@ -173,7 +173,7 @@ export abstract class BaseEditor extends LitElement { // .then(result => { // this.sourceList = result; // this.sourceListLastUpdatedOn = Date.now() / 1000; - // console.log("%c base-editor.render - updateSourceList AFTER update:\n %s=sourceListLastUpdatedOn", "color: green;", JSON.stringify(this.sourceListLastUpdatedOn)); + // //console.log("%c base-editor.render - updateSourceList AFTER update:\n %s=sourceListLastUpdatedOn", "color: green;", JSON.stringify(this.sourceListLastUpdatedOn)); // this.requestUpdate(); // }); //} diff --git a/src/editor/general-editor.ts b/src/editor/general-editor.ts index deb670e..1b2d924 100644 --- a/src/editor/general-editor.ts +++ b/src/editor/general-editor.ts @@ -58,12 +58,12 @@ const CONFIG_SETTINGS_SCHEMA = [ type: 'string', default: 35.15, }, - { - name: 'replaceHttpWithHttpsForThumbnails', - label: "Replace HTTP with HTTPS for image url's", - required: false, - selector: { boolean: {} }, - }, +// { +// name: 'imageUrlsReplaceHttpWithHttps', +// label: "Replace HTTP with HTTPS for image url's", +// required: false, +// selector: { boolean: {} }, +// }, ]; diff --git a/src/editor/pandora-browser-editor.ts b/src/editor/pandora-browser-editor.ts index eefa812..046cfcc 100644 --- a/src/editor/pandora-browser-editor.ts +++ b/src/editor/pandora-browser-editor.ts @@ -85,11 +85,11 @@ class PandoraSettingsEditor extends BaseEditor { // // if it has not been set, and fire the config-changed event to indicate // // the configuration has changed. // if ((!this.config.pandoraSourceAccount) && (result.length == 1)) { - // console.log("pandora-browser-editor.getSourceAccountsPandora() 1 account match; defaulting to account: %s", result[0]); + // //console.log("pandora-browser-editor.getSourceAccountsPandora() 1 account match; defaulting to account: %s", result[0]); // this.config.pandoraSourceAccount = result[0]; - // console.log("pandora-browser-editor.getSourceAccountsPandora() calling configChanged"); + // //console.log("pandora-browser-editor.getSourceAccountsPandora() calling configChanged"); // this.configChanged(); - // console.log("pandora-browser-editor.getSourceAccountsPandora() dispatching media-browser-refresh event"); + // //console.log("pandora-browser-editor.getSourceAccountsPandora() dispatching media-browser-refresh event"); // this.dispatchEvent(customEvent(MEDIA_BROWSER_REFRESH, 'PANDORA')); // } } diff --git a/src/main.ts b/src/main.ts index 2fd8417..766d812 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,7 +19,7 @@ console.groupCollapsed( ); console.log( "Wiki Docs:", - "https://github.com/thlucas1/homeassistantcomponent_soundtouchplus/wiki" + "https://github.com/thlucas1/homeassistantcomponent_soundtouchplus_card/wiki/Configuration-Options" ); console.groupEnd(); @@ -31,7 +31,7 @@ window.customCards.push({ type: 'soundtouchplus-card', name: 'SoundTouchPlus Card', description: 'Home Assistant UI card that supports features unique to the SoundTouchPlus custom integration', - //documentationURL: 'https://github.com/thlucas1/homeassistantcomponent_soundtouchplus/wiki', + //documentationURL: 'https://github.com/thlucas1/homeassistantcomponent_soundtouchplus_card/wiki/Configuration-Options', preview: true, }); diff --git a/src/model/store.ts b/src/model/store.ts index bb78a4a..f6b128b 100644 --- a/src/model/store.ts +++ b/src/model/store.ts @@ -51,7 +51,7 @@ export class Store { // initialize storage. this.hass = hass; this.config = config; - this.hassService = new HassService(hass, config, card, section); + this.hassService = new HassService(hass, card, section); this.soundTouchPlusService = new SoundTouchPlusService(hass, card, section); this.player = this.getMediaPlayerObject(playerId); this.section = section; diff --git a/src/sections/pandora-browser.ts b/src/sections/pandora-browser.ts index 5b0727a..2fcaf6e 100644 --- a/src/sections/pandora-browser.ts +++ b/src/sections/pandora-browser.ts @@ -9,7 +9,7 @@ import '../components/media-browser-icons'; import { Store } from '../model/store'; import { MediaPlayer } from '../model/media-player'; import { customEvent } from '../utils/utils'; -import { formatPlayerInfo } from '../utils/media-browser-utils'; +import { formatTitleInfo } from '../utils/media-browser-utils'; import { ITEM_SELECTED, PANDORA_BROWSER_REFRESH } from '../constants'; import { SoundTouchPlusService } from '../services/soundtouchplus-service'; import { CardConfig } from '../types/cardconfig' @@ -85,8 +85,8 @@ export class PandoraBrowser extends LitElement { //console.log(LOGPFX + "render()\n this.mediaList='%s'", JSON.stringify(this.mediaList)); // format title and sub-title details. - const title = formatPlayerInfo(this.player, this.config.pandoraBrowserTitle, this.medialistLastUpdatedOn); - const subtitle = formatPlayerInfo(this.player, this.config.pandoraBrowserSubTitle, this.medialistLastUpdatedOn); + const title = formatTitleInfo(this.config.pandoraBrowserTitle, this.config, this.player, this.medialistLastUpdatedOn); + const subtitle = formatTitleInfo(this.config.pandoraBrowserSubTitle, this.config, this.player, this.medialistLastUpdatedOn); return html` ${title ? html`
${title}
` : html``} @@ -128,7 +128,7 @@ export class PandoraBrowser extends LitElement { // // log exceptions. // const exObj = (ex as Error); - // console.log("STPC - Error rendering pandora browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); + // //console.log("STPC - Error rendering pandora browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); // return html`Could not render card - check console log`; } finally { @@ -243,7 +243,7 @@ export class PandoraBrowser extends LitElement { .then(result => { this.mediaList = result; this.medialistLastUpdatedOn = result.LastUpdatedOn || 0; - console.log("%c pandora-browser render - updateMediaList check info AFTER update:\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(this.medialistLastUpdatedOn)); + //console.log("%c pandora-browser render - updateMediaList check info AFTER update:\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(this.medialistLastUpdatedOn)); this.requestUpdate(); }); } diff --git a/src/sections/preset-browser.ts b/src/sections/preset-browser.ts index 4f00b1c..9612607 100644 --- a/src/sections/preset-browser.ts +++ b/src/sections/preset-browser.ts @@ -8,7 +8,7 @@ import '../components/media-browser-list'; import '../components/media-browser-icons'; import { Store } from '../model/store'; import { customEvent } from '../utils/utils'; -import { formatPlayerInfo } from '../utils/media-browser-utils'; +import { formatTitleInfo } from '../utils/media-browser-utils'; import { MediaPlayer } from '../model/media-player'; import { ITEM_SELECTED, ITEM_SELECTED_WITH_HOLD } from '../constants'; import { SoundTouchPlusService } from '../services/soundtouchplus-service'; @@ -81,7 +81,7 @@ export class PresetBrowser extends LitElement { // was the media player preset list updated? const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_presets_lastupdated || 0); - console.log("%c preset-browser render - updateMediaList check info BEFORE update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); + //console.log("%c preset-browser render - updateMediaList check info BEFORE update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); if ((playerLastUpdatedOn != this.medialistLastUpdatedOn) && (this.medialistLastUpdatedOn > 0)) this.updateMediaList(this.player); @@ -89,8 +89,8 @@ export class PresetBrowser extends LitElement { //console.log(LOGPFX + "render()\n this.mediaList='%s'", JSON.stringify(this.mediaList)); // format title and sub-title details. - const title = formatPlayerInfo(this.player, this.config.presetBrowserTitle); - const subtitle = formatPlayerInfo(this.player, this.config.presetBrowserSubTitle); + const title = formatTitleInfo(this.config.presetBrowserTitle, this.config, this.player); + const subtitle = formatTitleInfo(this.config.presetBrowserSubTitle, this.config, this.player); return html` ${title ? html`
${title}
` : html``} @@ -133,7 +133,7 @@ export class PresetBrowser extends LitElement { // // log exceptions. // const exObj = (ex as Error); - // console.log("STPC - Error rendering preset browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); + // //console.log("STPC - Error rendering preset browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); // return html`Could not render card - check console log`; } finally { @@ -212,14 +212,10 @@ export class PresetBrowser extends LitElement { // call the service to retrieve the media list. this.soundTouchPlusService.PresetList(player.id, true) .then(result => { - //if (player.attributes.media_title == 'I Need You') { // TEST TODO test for invalid lastupdatedon - // console.log("updateMediaList() - resetting result.LastUpdatedOn to undefined TEST TODO REMOVE ME"); - // result.LastUpdatedOn = undefined; // TEST TODO - //} // TEST TODO this.mediaList = result; this.medialistLastUpdatedOn = result.LastUpdatedOn || 0; - const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_presets_lastupdated || 0); - console.log("%c preset-browser render - updateMediaList check info AFTER update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); + //const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_presets_lastupdated || 0); + //console.log("%c preset-browser render - updateMediaList check info AFTER update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); this.requestUpdate(); }); } diff --git a/src/sections/recent-browser.ts b/src/sections/recent-browser.ts index 08b9235..6a17e17 100644 --- a/src/sections/recent-browser.ts +++ b/src/sections/recent-browser.ts @@ -8,7 +8,7 @@ import '../components/media-browser-list'; import '../components/media-browser-icons'; import { Store } from '../model/store'; import { customEvent } from '../utils/utils'; -import { formatPlayerInfo } from '../utils/media-browser-utils'; +import { formatTitleInfo } from '../utils/media-browser-utils'; import { MediaPlayer } from '../model/media-player'; import { ITEM_SELECTED } from '../constants'; import { SoundTouchPlusService } from '../services/soundtouchplus-service'; @@ -78,7 +78,7 @@ export class RecentBrowser extends LitElement { // was the media player recent list updated? const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_recents_lastupdated || 0); - console.log("%c recent-browser render - updateMediaList check info BEFORE update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); + //console.log("%c recent-browser render - updateMediaList check info BEFORE update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); if ((playerLastUpdatedOn != this.medialistLastUpdatedOn) && (this.medialistLastUpdatedOn > 0)) this.updateMediaList(this.player); @@ -86,8 +86,8 @@ export class RecentBrowser extends LitElement { //console.log(LOGPFX + "render()\n this.recentList='%s'", JSON.stringify(this.recentList)); // format title and sub-title details. - const title = formatPlayerInfo(this.player, this.config.recentBrowserTitle); - const subtitle = formatPlayerInfo(this.player, this.config.recentBrowserSubTitle); + const title = formatTitleInfo(this.config.recentBrowserTitle, this.config, this.player); + const subtitle = formatTitleInfo(this.config.recentBrowserSubTitle, this.config, this.player); return html` ${title ? html`
${title}
` : html``} @@ -128,7 +128,7 @@ export class RecentBrowser extends LitElement { // // log exceptions. // const exObj = (ex as Error); - // console.log("STPC - Error rendering recent browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); + // //console.log("STPC - Error rendering recent browser html\n Name = '%s'\nMessage = %s", exObj.name, exObj.message); // return html`Could not render card - check console log`; } finally { @@ -180,8 +180,8 @@ export class RecentBrowser extends LitElement { .then(result => { this.recentList = result; this.medialistLastUpdatedOn = result.LastUpdatedOn || 0; - const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_recents_lastupdated || 0); - console.log("%c recent-browser render - updateMediaList check info AFTER update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); + //const playerLastUpdatedOn = (this.player.attributes.soundtouchplus_recents_lastupdated || 0); + //console.log("%c recent-browser render - updateMediaList check info AFTER update:\n %s=playerLastUpdatedOn\n %s=medialistLastUpdatedOn", "color: green;", JSON.stringify(playerLastUpdatedOn), JSON.stringify(this.medialistLastUpdatedOn)); this.requestUpdate(); }); } diff --git a/src/services/hass-service.ts b/src/services/hass-service.ts index 5e699aa..cc2cc04 100644 --- a/src/services/hass-service.ts +++ b/src/services/hass-service.ts @@ -5,7 +5,7 @@ import { PROGRESS_DONE, PROGRESS_STARTED } from '../constants'; import { MediaPlayer } from '../model/media-player'; import { HassEntity } from 'home-assistant-js-websocket'; import { customEvent } from '../utils/utils'; -import { CardConfig } from '../types/cardconfig' +//import { CardConfig } from '../types/cardconfig' import { Section } from '../types/section' export class HassService { @@ -14,7 +14,7 @@ export class HassService { private readonly hass: HomeAssistant; /** Card configuration data. */ - private readonly config: CardConfig; + //private readonly config: CardConfig; /** Custom card instance. */ private readonly card: Element; @@ -27,13 +27,12 @@ export class HassService { * Initializes a new instance of the class. * * @param hass Home Assistant instance. - * @param config Card configuration data. * @param card Custom card instance. * @param section Currently selected section of the card. */ - constructor(hass: HomeAssistant, config: CardConfig, card: Element, section: Section) { + constructor(hass: HomeAssistant, card: Element, section: Section) { this.hass = hass; - this.config = config; + //this.config = config; this.card = card; this.section = section; } @@ -63,12 +62,12 @@ export class HassService { media_content_id, media_content_type, }); - if (this.config.replaceHttpWithHttpsForThumbnails) { - mediaPlayerItem.children = mediaPlayerItem.children?.map((child) => ({ - ...child, - thumbnail: child.thumbnail?.replace('http://', 'https://'), - })); - } + //if (this.config.imageUrlsReplaceHttpWithHttps) { + // mediaPlayerItem.children = mediaPlayerItem.children?.map((child) => ({ + // ...child, + // thumbnail: child.thumbnail?.replace('http://', 'https://'), + // })); + //} return mediaPlayerItem; } diff --git a/src/services/soundtouchplus-service.ts b/src/services/soundtouchplus-service.ts index 44cd12b..5e0f0a6 100644 --- a/src/services/soundtouchplus-service.ts +++ b/src/services/soundtouchplus-service.ts @@ -13,7 +13,7 @@ import { SourceList } from '../types/soundtouchplus/sourcelist'; import { Section } from '../types/section'; import { ServiceCallResponse } from '../types/servicecallresponse'; -const LOGPFX = "STPC - services/soundtouchplus-service." +//const LOGPFX = "STPC - services/soundtouchplus-service." /** SoundTouchPlus custom services provider class. */ @@ -54,7 +54,7 @@ export class SoundTouchPlusService { try { - console.log("%c" + LOGPFX + "CallService()\n Calling service '%s' (no response)\n%s", "color: orange;", serviceRequest.service, JSON.stringify(serviceRequest,null,2)); + //console.log("%c" + LOGPFX + "CallService()\n Calling service '%s' (no response)\n%s", "color: orange;", serviceRequest.service, JSON.stringify(serviceRequest,null,2)); // show the progress indicator on the main card. this.card.dispatchEvent(customEvent(PROGRESS_STARTED, { section: this.section })); @@ -87,7 +87,7 @@ export class SoundTouchPlusService { try { - console.log("%c" + LOGPFX + "CallServiceWithResponse()\n Calling service '%s' (with response)\n%s", "color: orange;", serviceRequest.service, JSON.stringify(serviceRequest, null, 2)); + //console.log("%c" + LOGPFX + "CallServiceWithResponse()\n Calling service '%s' (with response)\n%s", "color: orange;", serviceRequest.service, JSON.stringify(serviceRequest, null, 2)); // show the progress indicator on the main card. this.card.dispatchEvent(customEvent(PROGRESS_STARTED, { section: this.section })); diff --git a/src/types/cardconfig.ts b/src/types/cardconfig.ts index 8a710e5..e1bc1d0 100644 --- a/src/types/cardconfig.ts +++ b/src/types/cardconfig.ts @@ -17,6 +17,10 @@ export interface CardConfig extends LovelaceCardConfig { /** * Sections of the card to display. + * Valid values are: + * - `presets` Presets section will be displayed. + * - `recents` Recently Played section will be displayed. + * - `pandorastations` Pandora Stations section will be displayed. */ sections?: Section[]; @@ -70,7 +74,7 @@ export interface CardConfig extends LovelaceCardConfig { presetBrowserItemsHideTitle?: boolean; /** - * Hide source titles displayed for Pandora media browser items. + * Hide source titles displayed for Preset media browser items. * Default is false. */ presetBrowserItemsHideSource?: boolean; @@ -172,5 +176,5 @@ export interface CardConfig extends LovelaceCardConfig { fallbackArtwork?: string; - replaceHttpWithHttpsForThumbnails?: boolean; + //imageUrlsReplaceHttpWithHttps?: boolean; } diff --git a/src/utils/media-browser-utils.ts b/src/utils/media-browser-utils.ts index 491b069..5fd2947 100644 --- a/src/utils/media-browser-utils.ts +++ b/src/utils/media-browser-utils.ts @@ -108,6 +108,30 @@ export function itemsWithFallbacks(collection: ContentItemParent[], config: Card } +/** + * Formats a string with various configuration information. This method finds selected keywords + * and replaces them with the equivalent attribute values. + * + * @param text Text string to replace keyword values with. + * @param config CardConfig configuration data. + * @param player MediaPlayer instance that contains information about the player. + * @param lastUpdatedOn Epoch date (in seconds) when the last refresh of the media list took place. Only used for services that don't have a media player `lastupdatedon` attribute. + * @returns The text argument with keywords replaced with the equivalent attribute values. + */ +export function formatTitleInfo( + text: string | undefined, + config: CardConfig, + player: MediaPlayer, + lastUpdatedOn: number | undefined = undefined, +): string | undefined { + + // call various formatting methods. + let result = formatConfigInfo(text, config); + result = formatPlayerInfo(result, player, lastUpdatedOn); + return result; + +} + /** * Formats a string with MediaPlayer information. This method finds selected keywords * and replaces them with the equivalent MediaPlayer attribute values. @@ -117,14 +141,14 @@ export function itemsWithFallbacks(collection: ContentItemParent[], config: Card * - {player.soundtouchplus_presets_lastupdated} : Date and Time the preset list was last refreshed from the device. * - {player.soundtouchplus_recents_lastupdated} : Date and Time the recents list was last refreshed from the device. * - * @param player MediaPlayer instance that contains information about the player. * @param text Text string to replace media player keyword values with. - * @param lastUpdatedOn Epoch date (in seconds) when the last refresh of the media list took place. Only used for services that don't have a media player `lastupdated` attribute. + * @param player MediaPlayer instance that contains information about the player. + * @param lastUpdatedOn Epoch date (in seconds) when the last refresh of the media list took place. Only used for services that don't have a media player `lastupdatedon` attribute. * @returns The text argument with media player keywords replaced with media player details. */ export function formatPlayerInfo( - player: MediaPlayer, text: string | undefined, + player: MediaPlayer, lastUpdatedOn: number | undefined = undefined, ): string | undefined { @@ -136,6 +160,7 @@ export function formatPlayerInfo( if (text) { text = text.replace("{player.name}", player.name); + text = text.replace("{player.source}", player.attributes.source || ''); if (text.indexOf("{player.soundtouchplus_presets_lastupdated}") > -1) { const localeDT = formatDateEpochSecondsToLocaleString(player.attributes.soundtouchplus_presets_lastupdated) @@ -162,7 +187,6 @@ export function formatPlayerInfo( //media_artist: Big Daddy Weave //media_album_name: Love Come To Life //media_track: Redeemed - //source: Spotify(thlucas2010@gmail.com) //shuffle: false //repeat: "off" //soundtouchplus_nowplaying_isadvertisement: false @@ -184,6 +208,37 @@ export function formatPlayerInfo( } +/** + * Formats a string with CardConfig information. This method finds selected keywords + * and replaces them with the equivalent CardConfig attribute values. + * + * The following replacement keywords are supported: + * - {config.pandoraUserAccount} : player name (e.g. "Livingroom Soundbar"). + * + * @param text Text string to replace configuration keyword values with. + * @param config CardConfig configuration data. + * @returns The text argument with configuration keywords replaced with configuration details. + */ +export function formatConfigInfo( + text: string | undefined, + config: CardConfig, +): string | undefined { + + // if config instance not set then don't bother. + if (!config) + return text + + // replace keyword parameters with configuration equivalents. + if (text) { + + text = text.replace("{config.pandorasourceaccount}", config.pandoraSourceAccount || ''); + + } + + return text +} + + /** * Style definition used to style a media browser item background image. */