Skip to content

Commit

Permalink
[ 1.0.38 ] * Added card configuration option `searchMediaBrowserQueue…
Browse files Browse the repository at this point in the history
…Selection`; True to add track / episode to play queue when search result is clicked; Otherwise, false to play the track / episode immediately when track search result is clicked. Default is false.

  * Added theme variable `--spc-card-wait-progress-slider-color` and `cardWaitProgressSliderColor` card configuration option; Color of the card area wait progress indicator (default `#2196F3`).
  * Added theme variable `--spc-player-progress-label-color` and `playerProgressLabelColor` card configuration option; Color of the player progress text labels (default `#ffffff`).
  * Added theme variable `--spc-player-progress-slider-color` and `playerProgressSliderColor` card configuration option; Color of the player progress slider bar (default `#2196F3`).
  * Added theme variable `--spc-player-volume-label-color` and `playerVolumeLabelColor` card configuration option; Color of the player volume text labels (default `#ffffff`).
  * Added theme variable `--spc-player-volume-slider-color` and `playerVolumeSliderColor` card configuration option; Color of the player volume slider bar (default `#2196F3`).
  * Corrected a bug when displaying player queue; the queue would not render when it contained a mix of tracks, podcast episodes, and audiobook chapters.  Queue will now be displayed on the type of items in the queue, and not based on what the player is currently playing.
  • Loading branch information
thlucas1 committed Feb 7, 2025
1 parent 4229889 commit b857539
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 110 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ Change are listed in reverse chronological order (newest to oldest).

<span class="changelog">

###### [ 1.0.38 ] - 2025/02/07

* Added card configuration option `searchMediaBrowserQueueSelection`; True to add track / episode to play queue when search result is clicked; Otherwise, false to play the track / episode immediately when track search result is clicked. Default is false.
* Added theme variable `--spc-card-wait-progress-slider-color` and `cardWaitProgressSliderColor` card configuration option; Color of the card area wait progress indicator (default `#2196F3`).
* Added theme variable `--spc-player-progress-label-color` and `playerProgressLabelColor` card configuration option; Color of the player progress text labels (default `#ffffff`).
* Added theme variable `--spc-player-progress-slider-color` and `playerProgressSliderColor` card configuration option; Color of the player progress slider bar (default `#2196F3`).
* Added theme variable `--spc-player-volume-label-color` and `playerVolumeLabelColor` card configuration option; Color of the player volume text labels (default `#ffffff`).
* Added theme variable `--spc-player-volume-slider-color` and `playerVolumeSliderColor` card configuration option; Color of the player volume slider bar (default `#2196F3`).
* Corrected a bug when displaying player queue; the queue would not render when it contained a mix of tracks, podcast episodes, and audiobook chapters. Queue will now be displayed on the type of items in the queue, and not based on what the player is currently playing.

###### [ 1.0.37 ] - 2025/02/05

* Updated favorite browsers to clear cached filter criteria if the filter criteria textbox was cleared.
Expand Down
55 changes: 26 additions & 29 deletions src/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ export class Card extends LitElement {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
--mdc-theme-primary: var(--dark-primary-color);
--mdc-theme-primary: var(--spc-card-wait-progress-slider-color, var(--dark-primary-color, #2196F3));
}
.spc-not-configured {
Expand All @@ -350,7 +350,7 @@ export class Card extends LitElement {
}
ha-circular-progress {
--md-sys-color-primary: var(--dark-primary-color);
--md-sys-color-primary: var(--spc-card-wait-progress-slider-color, var(--dark-primary-color, #2196F3));
}
`;
}
Expand Down Expand Up @@ -1152,44 +1152,42 @@ export class Card extends LitElement {
let cardHeight: string | undefined = undefined;
let editTabHeight = '0px';
let editBottomToolbarHeight = '0px';
const cardWaitProgressSliderColor = this.config.cardWaitProgressSliderColor;

// build style info object.
const styleInfo: StyleInfo = <StyleInfo>{};
if (cardWaitProgressSliderColor)
styleInfo['--spc-card-wait-progress-slider-color'] = `${cardWaitProgressSliderColor}`;

// are we previewing the card in the card editor?
// if so, then we will ignore the configuration dimensions and use constants.
if (isCardInEditPreview(this)) {

// card is in edit preview.
cardHeight = CARD_EDIT_PREVIEW_HEIGHT;
cardWidth = CARD_EDIT_PREVIEW_WIDTH;
return styleMap({
'--spc-card-edit-tab-height': `${editTabHeight}`,
'--spc-card-edit-bottom-toolbar-height': `${editBottomToolbarHeight}`,
height: `${cardHeight ? cardHeight : undefined}`,
width: `${cardWidth ? cardWidth : undefined}`,
'background-repeat': `${!this.playerId ? 'no-repeat' : undefined}`,
'background-position': `${!this.playerId ? 'center' : undefined}`,
'background-image': `${!this.playerId ? 'url(' + BRAND_LOGO_IMAGE_BASE64 + ')' : undefined}`,
'background-size': `${!this.playerId ? BRAND_LOGO_IMAGE_SIZE : undefined}`,
});

styleInfo['--spc-card-edit-tab-height'] = `${editTabHeight}`;
styleInfo['--spc-card-edit-bottom-toolbar-height'] = `${editBottomToolbarHeight}`;
styleInfo['height'] = `${CARD_EDIT_PREVIEW_HEIGHT}`;
styleInfo['width'] = `${CARD_EDIT_PREVIEW_WIDTH}`;
styleInfo['background-repeat'] = `${!this.playerId ? 'no-repeat' : undefined}`;
styleInfo['background-position'] = `${!this.playerId ? 'center' : undefined}`;
styleInfo['background-image'] = `${!this.playerId ? 'url(' + BRAND_LOGO_IMAGE_BASE64 + ')' : undefined}`;
styleInfo['background-size'] = `${!this.playerId ? BRAND_LOGO_IMAGE_SIZE : undefined}`;
return styleMap(styleInfo);
}

// set card picker options.
if (isCardInPickerPreview(this)) {

// card is in pick preview.
cardHeight = CARD_PICK_PREVIEW_HEIGHT;
cardWidth = CARD_PICK_PREVIEW_WIDTH;
return styleMap({
'--spc-card-edit-tab-height': `${editTabHeight}`,
'--spc-card-edit-bottom-toolbar-height': `${editBottomToolbarHeight}`,
height: `${cardHeight ? cardHeight : undefined}`,
width: `${cardWidth ? cardWidth : undefined}`,
'background-repeat': `no-repeat`,
'background-position': `center`,
'background-image': `url(${BRAND_LOGO_IMAGE_BASE64})`,
'background-size': `${BRAND_LOGO_IMAGE_SIZE}`,
});

styleInfo['--spc-card-edit-tab-height'] = `${editTabHeight}`;
styleInfo['--spc-card-edit-bottom-toolbar-height'] = `${editBottomToolbarHeight}`;
styleInfo['height'] = `${CARD_PICK_PREVIEW_HEIGHT}`;
styleInfo['width'] = `${CARD_PICK_PREVIEW_WIDTH}`;
styleInfo['background-repeat'] = 'no-repeat';
styleInfo['background-position'] = 'center';
styleInfo['background-image'] = `url(${BRAND_LOGO_IMAGE_BASE64})`;
styleInfo['background-size'] = `${BRAND_LOGO_IMAGE_SIZE}`;
return styleMap(styleInfo);
}

// set card editor options.
Expand Down Expand Up @@ -1235,7 +1233,6 @@ export class Card extends LitElement {
//);

// build style info object.
const styleInfo: StyleInfo = <StyleInfo>{};
styleInfo['--spc-card-edit-tab-height'] = `${editTabHeight}`;
styleInfo['--spc-card-edit-bottom-toolbar-height'] = `${editBottomToolbarHeight}`;
styleInfo['height'] = `${cardHeight ? cardHeight : undefined}`;
Expand Down
101 changes: 34 additions & 67 deletions src/components/player-body-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { ITrack } from '../types/spotifyplus/track';
* Track actions.
*/
enum Actions {
ChapterPlay = "ChapterPlay",
EpisodePlay = "EpisodePlay",
GetPlayerQueueInfo = "GetPlayerQueueInfo",
TrackPlay = "TrackPlay",
Expand All @@ -49,67 +48,40 @@ export class PlayerBodyQueue extends PlayerBodyBase {
super.render();

// initialize common elements.
let queueInfoTitle = html`Unknown`;
let queueInfoParentTitle = html`Title Type`;
let queueItems = html`<div class="grid-entry queue-info-grid-no-items">No items found in Queue</div>`;

// generate queue items info based on content type.
if (this.player.attributes.sp_item_type == 'podcast') {

// build queue info display for podcast episodes.
queueInfoTitle = html`Episodes`;
queueInfoParentTitle = html`Show`;
if ((this.queueInfo?.queue || []).length > 0) {
queueItems = html`${this.queueInfo?.queue.map((item, index) => html`
<ha-icon-button
.path=${mdiPlay}
.label="Play track &quot;${item.name || ""}&quot;"
@click=${() => this.onClickAction(Actions.TrackPlay, item)}
slot="icon-button"
>&nbsp;</ha-icon-button>
<div class="grid-entry">${index + 1}</div>
<div class="grid-entry">${item.name || ""}</div>
<div class="grid-entry">${item.artists[0].name || ""}</div>
`)}`;
}

} else if (this.player.attributes.sp_item_type == 'audiobook') {

// build queue info display for audiobook chapters.
queueInfoTitle = html`Chapters`;
queueInfoParentTitle = html`Audiobook`;
if ((this.queueInfo?.queue || []).length > 0) {
queueItems = html`${this.queueInfo?.queue.map((item, index) => html`
<ha-icon-button
.path=${mdiPlay}
.label="Play episode &quot;${item.name || ""}&quot;"
@click=${() => this.onClickAction(Actions.ChapterPlay, item)}
slot="icon-button"
>&nbsp;</ha-icon-button>
<div class="grid-entry">${index + 1}</div>
<div class="grid-entry">${item.name || ""}</div>
<div class="grid-entry">${item.show?.name || ""}</div>
`)}`;
}

} else if (this.player.attributes.sp_item_type == 'track') {

// build queue info display for tracks.
queueInfoTitle = html`Tracks`;
queueInfoParentTitle = html`Artist`;
if ((this.queueInfo?.queue || []).length > 0) {
queueItems = html`${this.queueInfo?.queue.map((item, index) => html`
<ha-icon-button
.path=${mdiPlay}
.label="Play track &quot;${item.name || ""}&quot;"
@click=${() => this.onClickAction(Actions.TrackPlay, item)}
slot="icon-button"
>&nbsp;</ha-icon-button>
<div class="grid-entry">${index + 1}</div>
<div class="grid-entry">${item.name || ""}</div>
<div class="grid-entry">${item.artists[0].name || ""}</div>
`)}`;
}
// process all queue items.
if ((this.queueInfo?.queue || []).length > 0) {
queueItems = html`${this.queueInfo?.queue.map((item, index) => html`
${(() => {
// render based on item type (track, episode).
if (item.type == 'episode') {
return (html `
<ha-icon-button
.path=${mdiPlay}
.label="Play episode &quot;${item.name || ""}&quot;"
@click=${() => this.onClickAction(Actions.EpisodePlay, item)}
slot="icon-button"
>&nbsp;</ha-icon-button>
<div class="grid-entry">${index + 1}</div>
<div class="grid-entry">${item.name || ""}</div>
<div class="grid-entry">${item.show?.name || ""}</div>
`)
} else {
return (html `
<ha-icon-button
.path=${mdiPlay}
.label="Play track &quot;${item.name || ""}&quot;"
@click=${() => this.onClickAction(Actions.TrackPlay, item)}
slot="icon-button"
>&nbsp;</ha-icon-button>
<div class="grid-entry">${index + 1}</div>
<div class="grid-entry">${item.name || ""}</div>
<div class="grid-entry">${item.artists[0].name || ""}</div>
`)
}
})()}
`)}`;
}

// render html.
Expand All @@ -119,14 +91,14 @@ export class PlayerBodyQueue extends PlayerBodyBase {
${this.alertError ? html`<ha-alert alert-type="error" dismissable @alert-dismissed-clicked=${this.alertErrorClear}>${this.alertError}</ha-alert>` : ""}
${this.alertInfo ? html`<ha-alert alert-type="info" dismissable @alert-dismissed-clicked=${this.alertInfoClear}>${this.alertInfo}</ha-alert>` : ""}
<div class="media-info-text-ms-c queue-info-grid-container">
Player Queue Info - ${queueInfoTitle}
Player Queue Items
</div>
<div class="queue-info-grid-container">
<div class="grid queue-info-grid">
<div class="grid-header">&nbsp;</div>
<div class="grid-header">#</div>
<div class="grid-header">Title</div>
<div class="grid-header">${queueInfoParentTitle}</div>
<div class="grid-header">Artist / Show / Book</div>
${queueItems}
</div>
</div>
Expand Down Expand Up @@ -205,11 +177,6 @@ export class PlayerBodyQueue extends PlayerBodyBase {

this.updateActions(this.player, [Actions.GetPlayerQueueInfo]);

} else if (action == Actions.ChapterPlay) {

await this.spotifyPlusService.Card_PlayMediaBrowserItem(this.player, item);
this.progressHide();

} else if (action == Actions.EpisodePlay) {

await this.spotifyPlusService.Card_PlayMediaBrowserItem(this.player, item);
Expand Down
4 changes: 2 additions & 2 deletions src/components/player-progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class Progress extends LitElement {
width: 100%;
font-size: x-small;
display: flex;
color: var(--spc-player-controls-color, var(--spc-player-controls-icon-color, #ffffff));
color: var(--spc-player-progress-label-color, var(--spc-player-controls-color, #ffffff));
padding-bottom: 0.2rem;
}
Expand All @@ -237,7 +237,7 @@ class Progress extends LitElement {
.progress-bar {
align-self: center;
background-color: var(--dark-primary-color);
background-color: var(--spc-player-progress-slider-color, var(--spc-player-controls-color, var(--dark-primary-color, #2196F3)));
margin-left: 2px;
margin-right: 2px;
height: 50%;
Expand Down
6 changes: 3 additions & 3 deletions src/components/player-volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ class Volume extends LitElement {
static get styles() {
return css`
ha-control-slider {
--control-slider-color: var(--dark-primary-color);
--control-slider-color: var(--spc-player-volume-slider-color, var(--spc-player-controls-color, var(--dark-primary-color, #2196F3)));
--control-slider-thickness: 1rem;
}
Expand All @@ -362,7 +362,7 @@ class Volume extends LitElement {
flex: 1;
padding-right: 0.0rem;
align-content: flex-end;
color: var(--spc-player-controls-color, var(--spc-player-controls-icon-color, #ffffff));
color: var(--spc-player-volume-label-color, var(--spc-player-controls-color, #ffffff));
}
.volume-level {
Expand All @@ -376,7 +376,7 @@ class Volume extends LitElement {
padding-right: 2px;
font-weight: normal;
font-size: 10px;
color: var(--dark-primary-color);
color: var(--spc-player-volume-slider-color, var(--spc-player-controls-color, var(--dark-primary-color, #2196F3)));
}
*[slim] * {
Expand Down
4 changes: 2 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from 'lit';

/** current version of the card. */
export const CARD_VERSION = '1.0.37';
export const CARD_VERSION = '1.0.38';

/** SpotifyPlus integration domain identifier. */
export const DOMAIN_SPOTIFYPLUS = 'spotifyplus';
Expand Down Expand Up @@ -49,7 +49,7 @@ export const PLAYER_CONTROLS_BACKGROUND_COLOR_DEFAULT = '#000000BB';
/** default size of the icons in the Player controls area. */
export const PLAYER_CONTROLS_ICON_SIZE_DEFAULT = '2.0rem';

/** default size of the icons in the Player controls area. */
/** default color of toggled icons in the Player controls area. */
export const PLAYER_CONTROLS_ICON_TOGGLE_COLOR_DEFAULT = '#2196F3';

/** default size of the player background image. */
Expand Down
13 changes: 7 additions & 6 deletions src/editor/search-media-browser-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ const CONFIG_SETTINGS_SCHEMA = [
required: false,
selector: { boolean: {} },
},
//{
// name: 'searchMediaBrowserItemsSortTitle',
// label: 'Sort items by Title',
// required: false,
// selector: { boolean: {} },
//},
{
name: 'searchMediaBrowserQueueSelection',
label: 'Queue track / episode when selected',
help: 'otherwise play immediately',
required: false,
selector: { boolean: {} },
},
];


Expand Down
36 changes: 36 additions & 0 deletions src/sections/fav-browser-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,42 @@ export class FavBrowserBase extends LitElement {
}


/**
* Calls the SpotifyPlusService Card_PlayMediaBrowserItem method to play media.
*
* @param mediaItem The medialist item that was selected.
*/
protected async QueueMediaItem(mediaItem: any): Promise<void> {

try {

// show progress indicator.
this.progressShow();

// play media item.
await this.spotifyPlusService.AddPlayerQueueItems(this.player, mediaItem.uri);

// set info message and reset scroll position to zero so the message is displayed.
this.alertInfo = "Item added to play queue: \"" + mediaItem.name + "\".";
this.mediaBrowserContentElement.scrollTop = 0;

}
catch (error) {

// set error message and reset scroll position to zero so the message is displayed.
this.alertErrorSet("Could not play media item. " + getHomeAssistantErrorMessage(error));
this.mediaBrowserContentElement.scrollTop = 0;

}
finally {

// hide progress indicator.
this.progressHide();

}
}


/**
* Sets the scroll position on the media list content container.
*/
Expand Down
Loading

0 comments on commit b857539

Please sign in to comment.