Merge branch 'music' into main

pull/47/head
Juraj Nyíri 3 years ago
commit c8c2660a37

@ -17205,9 +17205,9 @@ const CSS_STYLE = {
}; };
const supported = { const supported = {
kodi: ['movie', 'episode', 'epg'], kodi: ['movie', 'episode', 'epg'],
androidtv: ['movie', 'show', 'season', 'episode', 'clip'], androidtv: ['movie', 'show', 'season', 'episode', 'clip', 'track', 'artist', 'album'],
plexPlayer: ['movie', 'show', 'season', 'episode', 'clip'], plexPlayer: ['movie', 'show', 'season', 'episode', 'clip', 'track', 'artist', 'album'],
cast: ['movie', 'episode'] cast: ['movie', 'episode', 'artist', 'album', 'track']
}; };
var bind = function bind(fn, thisArg) { var bind = function bind(fn, thisArg) {
@ -19240,6 +19240,13 @@ const sleep = async (ms) => {
const getState = async (hass, entityID) => { const getState = async (hass, entityID) => {
return hass.callApi('GET', `states/${entityID}`); return hass.callApi('GET', `states/${entityID}`);
}; };
const padWithZeroes = (number, length) => {
let myString = `${number}`;
while (myString.length < length) {
myString = `0${myString}`;
}
return myString;
};
const waitUntilState = async (hass, entityID, state) => { const waitUntilState = async (hass, entityID, state) => {
let entityState = await getState(hass, entityID); let entityState = await getState(hass, entityID);
while (entityState.state !== state) { while (entityState.state !== state) {
@ -19249,6 +19256,61 @@ const waitUntilState = async (hass, entityID, state) => {
await sleep(1000); await sleep(1000);
} }
}; };
const createTrackView = (playController, plex, data, fontSize1, fontSize2, isEven) => {
const margin1 = fontSize1 / 4;
const trackContainer = document.createElement('tr');
trackContainer.classList.add('trackContainer');
if (isEven) {
trackContainer.classList.add('even');
}
else {
trackContainer.classList.add('odd');
}
const trackIndexElem = document.createElement('td');
trackIndexElem.className = 'trackIndexElem';
trackIndexElem.innerHTML = `<span class="trackIndex">${escapeHtml(data.index)}</span>`;
trackIndexElem.style.fontSize = `${fontSize1}px`;
trackIndexElem.style.lineHeight = `${fontSize1}px`;
trackIndexElem.style.marginBottom = `${margin1}px`;
const trackInteractiveArea = document.createElement('div');
trackInteractiveArea.className = 'trackInteractiveArea';
if (playController) {
const trackPlayButton = playController.getPlayButton(data.type);
trackPlayButton.addEventListener('click', (trackEvent) => {
trackEvent.stopPropagation();
playController.play(data, true);
});
if (playController.isPlaySupported(data)) {
trackPlayButton.classList.remove('disabled');
}
trackInteractiveArea.append(trackPlayButton);
}
trackIndexElem.append(trackInteractiveArea);
trackContainer.append(trackIndexElem);
const trackTitleElem = document.createElement('td');
trackTitleElem.className = 'trackTitleElem';
trackTitleElem.innerHTML = escapeHtml(data.title);
trackTitleElem.style.fontSize = `${fontSize1}px`;
trackTitleElem.style.lineHeight = `${fontSize1}px`;
trackTitleElem.style.marginBottom = `${margin1}px`;
trackContainer.append(trackTitleElem);
const duration = lodash.get(data, 'Media[0].duration');
const trackLengthElem = document.createElement('td');
trackLengthElem.className = 'trackLengthElem';
trackLengthElem.style.fontSize = `${fontSize1}px`;
trackLengthElem.style.lineHeight = `${fontSize1}px`;
trackLengthElem.style.marginBottom = `${margin1}px`;
if (duration) {
const minutes = Math.floor(duration / 60 / 1000);
const seconds = Math.round((duration - minutes * 1000) / 6000);
trackLengthElem.innerHTML = escapeHtml(`${padWithZeroes(minutes, 2)}:${padWithZeroes(seconds, 2)}`);
}
trackContainer.append(trackLengthElem);
trackContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
return trackContainer;
};
const createEpisodesView = (playController, plex, data, fontSize1, fontSize2) => { const createEpisodesView = (playController, plex, data, fontSize1, fontSize2) => {
const episodeContainer = document.createElement('div'); const episodeContainer = document.createElement('div');
episodeContainer.className = 'episodeContainer'; episodeContainer.className = 'episodeContainer';
@ -19450,6 +19512,39 @@ class PlayController {
: processData.librarySectionTitle; : processData.librarySectionTitle;
try { try {
switch (processData.type) { switch (processData.type) {
case 'artist':
await this.playViaCastPlex(entity.value, 'MUSIC', `plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.title,
shuffle: 1
})}`);
break;
case 'album':
await this.playViaCastPlex(entity.value, 'MUSIC', `plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.parentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
album_name: processData.title,
shuffle: 1
})}`);
break;
case 'track':
await this.playViaCastPlex(entity.value, 'MUSIC', `plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.grandparentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
album_name: processData.parentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
track_name: processData.title,
shuffle: 1
})}`);
break;
case 'movie': case 'movie':
await this.playViaCastPlex(entity.value, 'movie', `plex://${JSON.stringify({ await this.playViaCastPlex(entity.value, 'movie', `plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase // eslint-disable-next-line @typescript-eslint/camelcase
@ -19470,7 +19565,12 @@ class PlayController {
})}`); })}`);
break; break;
default: default:
this.playViaCast(entity.value, processData.Media[0].Part[0].key); if (!lodash.isNil(processData.Media)) {
this.playViaCast(entity.value, processData.Media[0].Part[0].key);
}
else {
console.error('Casting this content directly is not possible. Consider using Plex integration.');
}
} }
} }
catch (err) { catch (err) {
@ -21221,6 +21321,55 @@ style.textContent = css `
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.trackContainer {
width: 100%;
}
.trackContainer.odd:hover,
.trackContainer.even:hover {
background-color: rgba(255, 255, 255, 0.2);
}
.trackInteractiveArea {
width: 14px;
height: 14px;
}
.trackInteractiveArea button[name='playButton'] {
width: 30px;
height: 30px;
top: inherit;
left: inherit;
margin-top: -7px;
margin-left: -3px;
}
.trackContainer.odd:hover .trackIndexElem .trackIndex,
.trackContainer.even:hover .trackIndexElem .trackIndex {
display: none;
}
.trackContainer.odd:hover .trackIndexElem .trackInteractiveArea,
.trackContainer.even:hover .trackIndexElem .trackInteractiveArea {
display: block;
}
.trackContainer.odd .trackIndexElem .trackInteractiveArea,
.trackContainer.even .trackIndexElem .trackInteractiveArea {
display: none;
}
.trackContainer.odd {
background-color: rgba(255, 255, 255, 0.08);
}
.trackContainer.even {
background-color: rgba(255, 255, 255, 0.04);
}
.trackLengthElem {
position: relative;
padding: 15px 20px 15px 10px;
}
.trackIndexElem {
position: relative;
padding: 15px 20px 15px 10px;
}
.trackTitleElem {
width: 100%;
}
.detail { .detail {
position: absolute; position: absolute;
left: 247px; left: 247px;
@ -22342,8 +22491,14 @@ class PlexMeetsHomeAssistant extends HTMLElement {
const moveElem = (elem) => { const moveElem = (elem) => {
const seasonElemLocal = elem; const seasonElemLocal = elem;
seasonElemLocal.style.marginTop = '0'; seasonElemLocal.style.marginTop = '0';
seasonElemLocal.style.width = `${CSS_STYLE.width}px`; if (lodash.isEqual(seasonElem.dataset.type, 'album')) {
seasonElemLocal.style.height = `${CSS_STYLE.height - 3}px`; seasonElemLocal.style.width = `${CSS_STYLE.width}px`;
seasonElemLocal.style.height = `${CSS_STYLE.width}px`;
}
else {
seasonElemLocal.style.width = `${CSS_STYLE.width}px`;
seasonElemLocal.style.height = `${CSS_STYLE.height - 3}px`;
}
seasonElemLocal.style.zIndex = '3'; seasonElemLocal.style.zIndex = '3';
seasonElemLocal.style.marginLeft = `0px`; seasonElemLocal.style.marginLeft = `0px`;
seasonElemLocal.dataset.clicked = 'false'; seasonElemLocal.dataset.clicked = 'false';
@ -22646,17 +22801,22 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.detailElem.style.color = 'rgba(255,255,255,1)'; this.detailElem.style.color = 'rgba(255,255,255,1)';
this.detailElem.style.zIndex = '4'; this.detailElem.style.zIndex = '4';
this.detailElem.style.width = `calc(100% - ${this.minExpandedWidth + 30 + 20}px)`; this.detailElem.style.width = `calc(100% - ${this.minExpandedWidth + 30 + 20}px)`;
this.detailElem.style.maxHeight = `${this.minExpandedHeight + 20}px`; if (this.activeMovieElem) {
this.detailElem.style.maxHeight = `${getHeight(this.activeMovieElem) + 40}px`;
}
else {
this.detailElem.style.maxHeight = `${this.minExpandedHeight + 20}px`;
}
} }
}, 200); }, 200);
} }
if (this.plex) { if (this.plex) {
let seasonsData = {}; let childrenData = {};
if (lodash.isEqual(data.type, 'episode')) { if (lodash.isEqual(data.type, 'episode')) {
seasonsData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]); childrenData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]);
} }
else if (data.childCount > 0) { else if (data.childCount > 0 || lodash.isEqual(data.type, 'artist')) {
seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); childrenData = await this.plex.getLibraryData(data.key.split('/')[3]);
} }
let dataDetails = {}; let dataDetails = {};
if (!lodash.isNil(data.key)) { if (!lodash.isNil(data.key)) {
@ -22760,7 +22920,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
} }
} }
if (!lodash.isEmpty(seasonsData)) { if (!lodash.isEmpty(childrenData)) {
this.seasonElemFreshlyLoaded = true; this.seasonElemFreshlyLoaded = true;
if (this.seasonsElem) { if (this.seasonsElem) {
this.seasonsElem.style.display = 'block'; this.seasonsElem.style.display = 'block';
@ -22768,42 +22928,47 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.seasonsElem.style.transition = `0s`; this.seasonsElem.style.transition = `0s`;
this.seasonsElem.style.top = `${top + 2000}px`; this.seasonsElem.style.top = `${top + 2000}px`;
} }
lodash.forEach(seasonsData, seasonData => { lodash.forEach(childrenData, childData => {
if (this.seasonsElem && this.plex) { if (this.seasonsElem && this.plex) {
this.seasonsElemHidden = false; this.seasonsElemHidden = false;
const seasonContainer = document.createElement('div'); const seasonContainer = document.createElement('div');
seasonContainer.className = 'seasonContainer'; seasonContainer.className = 'seasonContainer';
seasonContainer.style.width = `${CSS_STYLE.width}px`; seasonContainer.style.width = `${CSS_STYLE.width}px`;
const thumbURL = `${this.plex.getBasicURL()}/photo/:/transcode?width=${this.minExpandedWidth}&height=${this.minExpandedHeight}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; const thumbURL = `${this.plex.getBasicURL()}/photo/:/transcode?width=${this.minExpandedWidth}&height=${this.minExpandedHeight}&minSize=1&upscale=1&url=${childData.thumb}&X-Plex-Token=${this.config.token}`;
const seasonElem = document.createElement('div'); const seasonElem = document.createElement('div');
seasonElem.className = 'seasonElem'; seasonElem.className = 'seasonElem';
seasonElem.style.width = `${CSS_STYLE.width}px`; seasonElem.style.width = `${CSS_STYLE.width}px`;
seasonElem.style.height = `${CSS_STYLE.height - 3}px`; if (lodash.isEqual(childData.type, 'album')) {
seasonElem.style.height = `${CSS_STYLE.width}px`;
}
else {
seasonElem.style.height = `${CSS_STYLE.height - 3}px`;
}
seasonElem.style.backgroundImage = `url('${thumbURL}')`; seasonElem.style.backgroundImage = `url('${thumbURL}')`;
seasonElem.dataset.clicked = 'false'; seasonElem.dataset.clicked = 'false';
if (this.playController && !this.playController.isPlaySupported(seasonData)) { if (this.playController && !this.playController.isPlaySupported(childData)) {
seasonElem.style.cursor = 'pointer'; seasonElem.style.cursor = 'pointer';
} }
const interactiveArea = document.createElement('div'); const interactiveArea = document.createElement('div');
interactiveArea.className = 'interactiveArea'; interactiveArea.className = 'interactiveArea';
if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { if (childData.leafCount - childData.viewedLeafCount > 0) {
const toViewElem = document.createElement('div'); const toViewElem = document.createElement('div');
toViewElem.className = 'toViewSeason'; toViewElem.className = 'toViewSeason';
toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString();
toViewElem.style.fontSize = `${this.fontSize4}px`; toViewElem.style.fontSize = `${this.fontSize4}px`;
toViewElem.style.lineHeight = `${this.fontSize4}px`; toViewElem.style.lineHeight = `${this.fontSize4}px`;
toViewElem.style.padding = `${this.fontSize4 / 2}px`; toViewElem.style.padding = `${this.fontSize4 / 2}px`;
interactiveArea.appendChild(toViewElem); interactiveArea.appendChild(toViewElem);
} }
if (this.playController) { if (this.playController) {
const playButton = this.playController.getPlayButton(seasonData.type); const playButton = this.playController.getPlayButton(childData.type);
if (this.playController.isPlaySupported(seasonData)) { if (this.playController.isPlaySupported(childData)) {
playButton.classList.remove('disabled'); playButton.classList.remove('disabled');
} }
playButton.addEventListener('click', event => { playButton.addEventListener('click', event => {
event.stopPropagation(); event.stopPropagation();
if (this.plex && this.playController) { if (this.plex && this.playController) {
this.playController.play(seasonData, true); this.playController.play(childData, true);
} }
}); });
interactiveArea.append(playButton); interactiveArea.append(playButton);
@ -22812,13 +22977,18 @@ class PlexMeetsHomeAssistant extends HTMLElement {
seasonContainer.append(seasonElem); seasonContainer.append(seasonElem);
const seasonTitleElem = document.createElement('div'); const seasonTitleElem = document.createElement('div');
seasonTitleElem.className = 'seasonTitleElem'; seasonTitleElem.className = 'seasonTitleElem';
seasonTitleElem.innerHTML = escapeHtml(seasonData.title); seasonTitleElem.innerHTML = escapeHtml(childData.title);
seasonTitleElem.style.fontSize = `${this.fontSize1}px`; seasonTitleElem.style.fontSize = `${this.fontSize1}px`;
seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; seasonTitleElem.style.lineHeight = `${this.fontSize1}px`;
seasonContainer.append(seasonTitleElem); seasonContainer.append(seasonTitleElem);
const seasonEpisodesCount = document.createElement('div'); const seasonEpisodesCount = document.createElement('div');
seasonEpisodesCount.className = 'seasonEpisodesCount'; seasonEpisodesCount.className = 'seasonEpisodesCount';
seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; if (childData.leafCount > 0) {
seasonEpisodesCount.innerHTML = `${escapeHtml(childData.leafCount)} episodes`;
}
else if (!lodash.isNil(childData.year)) {
seasonEpisodesCount.innerHTML = `${escapeHtml(childData.year)} `;
}
seasonEpisodesCount.style.fontSize = `${this.fontSize2}px`; seasonEpisodesCount.style.fontSize = `${this.fontSize2}px`;
seasonEpisodesCount.style.lineHeight = `${this.fontSize2}px`; seasonEpisodesCount.style.lineHeight = `${this.fontSize2}px`;
seasonContainer.append(seasonEpisodesCount); seasonContainer.append(seasonEpisodesCount);
@ -22832,12 +23002,12 @@ class PlexMeetsHomeAssistant extends HTMLElement {
if (this.activeMovieElem) { if (this.activeMovieElem) {
if (seasonElem.dataset.clicked === 'false') { if (seasonElem.dataset.clicked === 'false') {
if (this.playController) { if (this.playController) {
this.playController.setPlayActionButtonType(seasonData.type); this.playController.setPlayActionButtonType(childData.type);
this.playController.setPlayButtonClickFunction((thisEvent) => { this.playController.setPlayButtonClickFunction((thisEvent) => {
thisEvent.preventDefault(); thisEvent.preventDefault();
thisEvent.stopPropagation(); thisEvent.stopPropagation();
if (this.playController) { if (this.playController) {
this.playController.play(seasonData, true); this.playController.play(childData, true);
} }
}); });
} }
@ -22852,37 +23022,68 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
}, 500); }, 500);
this.scrollDownInactiveSeasons(); this.scrollDownInactiveSeasons();
seasonContainer.style.top = `${-this.minExpandedHeight}px`; if (this.activeMovieElem) {
seasonContainer.style.top = `${-getHeight(this.activeMovieElem)}px`;
}
else {
seasonContainer.style.top = `${-this.minExpandedHeight}px`;
}
seasonElem.dataset.type = childData.type;
seasonElem.style.width = `${this.minExpandedWidth}px`; seasonElem.style.width = `${this.minExpandedWidth}px`;
seasonElem.style.height = `${this.minExpandedHeight - 6}px`; if (lodash.isEqual(childData.type, 'album')) {
seasonElem.style.height = `${this.minExpandedWidth}px`;
}
else {
seasonElem.style.height = `${this.minExpandedHeight - 6}px`;
}
seasonElem.style.zIndex = '3'; seasonElem.style.zIndex = '3';
seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - seasonElem.style.marginLeft = `-${getOffset(seasonElem).left -
getOffset(this.activeMovieElem).left}px`; getOffset(this.activeMovieElem).left}px`;
seasonTitleElem.style.color = 'rgba(255,255,255,0)'; seasonTitleElem.style.color = 'rgba(255,255,255,0)';
seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; seasonEpisodesCount.style.color = 'rgba(255,255,255,0)';
if (this.detailElem) { if (this.detailElem) {
this.detailElem.children[1].innerHTML = seasonData.title; this.detailElem.children[1].innerHTML = childData.title;
} }
(async () => { (async () => {
if (seasonData.leafCount > 0 && this.plex) { if (this.plex && (childData.leafCount > 0 || lodash.isEqual(childData.type, 'album'))) {
this.episodesElemFreshlyLoaded = true; this.episodesElemFreshlyLoaded = true;
const episodesData = await this.plex.getLibraryData(seasonData.key.split('/')[3]); const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]);
if (this.episodesElem) { if (this.episodesElem) {
this.episodesElemHidden = false; this.episodesElemHidden = false;
this.episodesElem.style.display = 'block'; this.episodesElem.style.display = 'block';
this.episodesElem.innerHTML = ''; this.episodesElem.innerHTML = '';
this.episodesElem.style.transition = `0s`; this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`; this.episodesElem.style.top = `${top + 2000}px`;
const tableView = document.createElement('table');
tableView.style.width = 'calc(100% - 10px)';
tableView.style.border = 'none';
tableView.cellSpacing = '0';
tableView.cellPadding = '0';
if (lodash.isEqual(childData.type, 'album')) {
this.episodesElem.append(tableView);
}
let isEven = false;
lodash.forEach(episodesData, episodeData => { lodash.forEach(episodesData, episodeData => {
if (this.episodesElem && this.playController && this.plex) { if (this.episodesElem && this.playController && this.plex) {
this.episodesElem.append(createEpisodesView(this.playController, this.plex, episodeData, this.fontSize1, this.fontSize2)); if (lodash.isEqual(episodeData.type, 'track')) {
tableView.append(createTrackView(this.playController, this.plex, episodeData, this.fontSize1, this.fontSize2, isEven));
isEven = !isEven;
}
else {
this.episodesElem.append(createEpisodesView(this.playController, this.plex, episodeData, this.fontSize1, this.fontSize2));
}
} }
}); });
clearInterval(this.episodesLoadTimeout); clearInterval(this.episodesLoadTimeout);
this.episodesLoadTimeout = setTimeout(() => { this.episodesLoadTimeout = setTimeout(() => {
if (this.episodesElem) { if (this.episodesElem) {
this.episodesElem.style.transition = `0.7s`; this.episodesElem.style.transition = `0.7s`;
this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; if (this.activeMovieElem) {
this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`;
}
else {
this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`;
}
this.resizeBackground(); this.resizeBackground();
} }
}, 200); }, 200);
@ -22897,7 +23098,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
else { else {
// todo: change title from season and change media type of play button back // todo: change title from season and change media type of play button back
if (this.playController) { if (this.playController) {
this.playController.setPlayActionButtonType(seasonData.type); this.playController.setPlayActionButtonType(childData.type);
} }
seasonContainer.style.top = `${seasonContainer.dataset.top}px`; seasonContainer.style.top = `${seasonContainer.dataset.top}px`;
this.minimizeSeasons(); this.minimizeSeasons();
@ -22942,7 +23143,12 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.showSeasonElemTimeout = setTimeout(() => { this.showSeasonElemTimeout = setTimeout(() => {
if (this.seasonsElem) { if (this.seasonsElem) {
this.seasonsElem.style.transition = `0.7s`; this.seasonsElem.style.transition = `0.7s`;
this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`; if (this.activeMovieElem) {
this.seasonsElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`;
}
else {
this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`;
}
this.resizeBackground(); this.resizeBackground();
} }
}, 200); }, 200);
@ -23096,8 +23302,10 @@ class PlexMeetsHomeAssistant extends HTMLElement {
movieElem.className = 'movieElem'; movieElem.className = 'movieElem';
movieElem.style.width = `${CSS_STYLE.width}px`; movieElem.style.width = `${CSS_STYLE.width}px`;
movieElem.style.height = `${CSS_STYLE.height}px`; movieElem.style.height = `${CSS_STYLE.height}px`;
if (!lodash.isNil(data.channelCallSign)) { if (!lodash.isNil(data.channelCallSign) || lodash.isEqual(data.type, 'artist')) {
movieElem.style.backgroundSize = '80%'; if (!lodash.isEqual(data.type, 'artist')) {
movieElem.style.backgroundSize = '80%';
}
movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)'; movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)';
movieElem.style.backgroundPosition = 'center'; movieElem.style.backgroundPosition = 'center';
movieElem.style.height = `${CSS_STYLE.width}px`; movieElem.style.height = `${CSS_STYLE.width}px`;

@ -10,9 +10,9 @@ const CSS_STYLE: any = {
const supported: any = { const supported: any = {
kodi: ['movie', 'episode', 'epg'], kodi: ['movie', 'episode', 'epg'],
androidtv: ['movie', 'show', 'season', 'episode', 'clip'], androidtv: ['movie', 'show', 'season', 'episode', 'clip', 'track', 'artist', 'album'],
plexPlayer: ['movie', 'show', 'season', 'episode', 'clip'], plexPlayer: ['movie', 'show', 'season', 'episode', 'clip', 'track', 'artist', 'album'],
cast: ['movie', 'episode'] cast: ['movie', 'episode', 'artist', 'album', 'track']
}; };
const LOREM_IPSUM = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec semper risus vitae aliquet interdum. Nulla facilisi. Pellentesque viverra sagittis lorem eget aliquet. Cras vehicula, purus vel consectetur mattis, ipsum arcu ullamcorper mi, id viverra purus ex eu dolor. Integer vehicula lacinia sem convallis iaculis. Nulla fermentum erat interdum, efficitur felis in, mollis neque. Vivamus luctus metus eget nisl pellentesque, placerat elementum magna eleifend. const LOREM_IPSUM = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec semper risus vitae aliquet interdum. Nulla facilisi. Pellentesque viverra sagittis lorem eget aliquet. Cras vehicula, purus vel consectetur mattis, ipsum arcu ullamcorper mi, id viverra purus ex eu dolor. Integer vehicula lacinia sem convallis iaculis. Nulla fermentum erat interdum, efficitur felis in, mollis neque. Vivamus luctus metus eget nisl pellentesque, placerat elementum magna eleifend.

@ -173,6 +173,51 @@ class PlayController {
: processData.librarySectionTitle; : processData.librarySectionTitle;
try { try {
switch (processData.type) { switch (processData.type) {
case 'artist':
await this.playViaCastPlex(
entity.value,
'MUSIC',
`plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.title,
shuffle: 1
})}`
);
break;
case 'album':
await this.playViaCastPlex(
entity.value,
'MUSIC',
`plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.parentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
album_name: processData.title,
shuffle: 1
})}`
);
break;
case 'track':
await this.playViaCastPlex(
entity.value,
'MUSIC',
`plex://${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/camelcase
library_name: libraryName,
// eslint-disable-next-line @typescript-eslint/camelcase
artist_name: processData.grandparentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
album_name: processData.parentTitle,
// eslint-disable-next-line @typescript-eslint/camelcase
track_name: processData.title,
shuffle: 1
})}`
);
break;
case 'movie': case 'movie':
await this.playViaCastPlex( await this.playViaCastPlex(
entity.value, entity.value,
@ -201,7 +246,11 @@ class PlayController {
); );
break; break;
default: default:
this.playViaCast(entity.value, processData.Media[0].Part[0].key); if (!_.isNil(processData.Media)) {
this.playViaCast(entity.value, processData.Media[0].Part[0].key);
} else {
console.error('Casting this content directly is not possible. Consider using Plex integration.');
}
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);

@ -181,6 +181,55 @@ style.textContent = css`
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.trackContainer {
width: 100%;
}
.trackContainer.odd:hover,
.trackContainer.even:hover {
background-color: rgba(255, 255, 255, 0.2);
}
.trackInteractiveArea {
width: 14px;
height: 14px;
}
.trackInteractiveArea button[name='playButton'] {
width: 30px;
height: 30px;
top: inherit;
left: inherit;
margin-top: -7px;
margin-left: -3px;
}
.trackContainer.odd:hover .trackIndexElem .trackIndex,
.trackContainer.even:hover .trackIndexElem .trackIndex {
display: none;
}
.trackContainer.odd:hover .trackIndexElem .trackInteractiveArea,
.trackContainer.even:hover .trackIndexElem .trackInteractiveArea {
display: block;
}
.trackContainer.odd .trackIndexElem .trackInteractiveArea,
.trackContainer.even .trackIndexElem .trackInteractiveArea {
display: none;
}
.trackContainer.odd {
background-color: rgba(255, 255, 255, 0.08);
}
.trackContainer.even {
background-color: rgba(255, 255, 255, 0.04);
}
.trackLengthElem {
position: relative;
padding: 15px 20px 15px 10px;
}
.trackIndexElem {
position: relative;
padding: 15px 20px 15px 10px;
}
.trackTitleElem {
width: 100%;
}
.detail { .detail {
position: absolute; position: absolute;
left: 247px; left: 247px;

@ -167,6 +167,15 @@ const getState = async (hass: HomeAssistant, entityID: string): Promise<Record<s
return hass.callApi('GET', `states/${entityID}`); return hass.callApi('GET', `states/${entityID}`);
}; };
const padWithZeroes = (number: number, length: number): string => {
let myString = `${number}`;
while (myString.length < length) {
myString = `0${myString}`;
}
return myString;
};
const waitUntilState = async (hass: HomeAssistant, entityID: string, state: string): Promise<void> => { const waitUntilState = async (hass: HomeAssistant, entityID: string, state: string): Promise<void> => {
let entityState = await getState(hass, entityID); let entityState = await getState(hass, entityID);
@ -178,6 +187,79 @@ const waitUntilState = async (hass: HomeAssistant, entityID: string, state: stri
} }
}; };
const createTrackView = (
playController: any,
plex: Plex,
data: Record<string, any>,
fontSize1: number,
fontSize2: number,
isEven: boolean
): HTMLElement => {
const margin1 = fontSize1 / 4;
const margin2 = fontSize2 / 4;
const trackContainer = document.createElement('tr');
trackContainer.classList.add('trackContainer');
if (isEven) {
trackContainer.classList.add('even');
} else {
trackContainer.classList.add('odd');
}
const trackIndexElem = document.createElement('td');
trackIndexElem.className = 'trackIndexElem';
trackIndexElem.innerHTML = `<span class="trackIndex">${escapeHtml(data.index)}</span>`;
trackIndexElem.style.fontSize = `${fontSize1}px`;
trackIndexElem.style.lineHeight = `${fontSize1}px`;
trackIndexElem.style.marginBottom = `${margin1}px`;
const trackInteractiveArea = document.createElement('div');
trackInteractiveArea.className = 'trackInteractiveArea';
if (playController) {
const trackPlayButton = playController.getPlayButton(data.type);
trackPlayButton.addEventListener('click', (trackEvent: MouseEvent) => {
trackEvent.stopPropagation();
playController.play(data, true);
});
if (playController.isPlaySupported(data)) {
trackPlayButton.classList.remove('disabled');
}
trackInteractiveArea.append(trackPlayButton);
}
trackIndexElem.append(trackInteractiveArea);
trackContainer.append(trackIndexElem);
const trackTitleElem = document.createElement('td');
trackTitleElem.className = 'trackTitleElem';
trackTitleElem.innerHTML = escapeHtml(data.title);
trackTitleElem.style.fontSize = `${fontSize1}px`;
trackTitleElem.style.lineHeight = `${fontSize1}px`;
trackTitleElem.style.marginBottom = `${margin1}px`;
trackContainer.append(trackTitleElem);
const duration = _.get(data, 'Media[0].duration');
const trackLengthElem = document.createElement('td');
trackLengthElem.className = 'trackLengthElem';
trackLengthElem.style.fontSize = `${fontSize1}px`;
trackLengthElem.style.lineHeight = `${fontSize1}px`;
trackLengthElem.style.marginBottom = `${margin1}px`;
if (duration) {
const minutes = Math.floor(duration / 60 / 1000);
const seconds = Math.round((duration - minutes * 1000) / 6000);
trackLengthElem.innerHTML = escapeHtml(`${padWithZeroes(minutes, 2)}:${padWithZeroes(seconds, 2)}`);
}
trackContainer.append(trackLengthElem);
trackContainer.addEventListener('click', episodeEvent => {
episodeEvent.stopPropagation();
});
return trackContainer;
};
const createEpisodesView = ( const createEpisodesView = (
playController: any, playController: any,
plex: Plex, plex: Plex,
@ -301,5 +383,6 @@ export {
clickHandler, clickHandler,
fetchEntityRegistry, fetchEntityRegistry,
waitUntilState, waitUntilState,
getState getState,
createTrackView
}; };

@ -19,7 +19,8 @@ import {
getDetailsBottom, getDetailsBottom,
clickHandler, clickHandler,
fetchEntityRegistry, fetchEntityRegistry,
getWidth getWidth,
createTrackView
} from './modules/utils'; } from './modules/utils';
import style from './modules/style'; import style from './modules/style';
@ -977,8 +978,13 @@ class PlexMeetsHomeAssistant extends HTMLElement {
const moveElem = (elem: HTMLElement): void => { const moveElem = (elem: HTMLElement): void => {
const seasonElemLocal = elem; const seasonElemLocal = elem;
seasonElemLocal.style.marginTop = '0'; seasonElemLocal.style.marginTop = '0';
seasonElemLocal.style.width = `${CSS_STYLE.width}px`; if (_.isEqual(seasonElem.dataset.type, 'album')) {
seasonElemLocal.style.height = `${CSS_STYLE.height - 3}px`; seasonElemLocal.style.width = `${CSS_STYLE.width}px`;
seasonElemLocal.style.height = `${CSS_STYLE.width}px`;
} else {
seasonElemLocal.style.width = `${CSS_STYLE.width}px`;
seasonElemLocal.style.height = `${CSS_STYLE.height - 3}px`;
}
seasonElemLocal.style.zIndex = '3'; seasonElemLocal.style.zIndex = '3';
seasonElemLocal.style.marginLeft = `0px`; seasonElemLocal.style.marginLeft = `0px`;
seasonElemLocal.dataset.clicked = 'false'; seasonElemLocal.dataset.clicked = 'false';
@ -1303,16 +1309,20 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.detailElem.style.color = 'rgba(255,255,255,1)'; this.detailElem.style.color = 'rgba(255,255,255,1)';
this.detailElem.style.zIndex = '4'; this.detailElem.style.zIndex = '4';
this.detailElem.style.width = `calc(100% - ${this.minExpandedWidth + 30 + 20}px)`; this.detailElem.style.width = `calc(100% - ${this.minExpandedWidth + 30 + 20}px)`;
this.detailElem.style.maxHeight = `${this.minExpandedHeight + 20}px`; if (this.activeMovieElem) {
this.detailElem.style.maxHeight = `${getHeight(this.activeMovieElem) + 40}px`;
} else {
this.detailElem.style.maxHeight = `${this.minExpandedHeight + 20}px`;
}
} }
}, 200); }, 200);
} }
if (this.plex) { if (this.plex) {
let seasonsData: Record<string, any> = {}; let childrenData: Record<string, any> = {};
if (_.isEqual(data.type, 'episode')) { if (_.isEqual(data.type, 'episode')) {
seasonsData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]); childrenData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]);
} else if (data.childCount > 0) { } else if (data.childCount > 0 || _.isEqual(data.type, 'artist')) {
seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); childrenData = await this.plex.getLibraryData(data.key.split('/')[3]);
} }
let dataDetails: Record<string, any> = {}; let dataDetails: Record<string, any> = {};
if (!_.isNil(data.key)) { if (!_.isNil(data.key)) {
@ -1424,7 +1434,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
} }
} }
if (!_.isEmpty(seasonsData)) { if (!_.isEmpty(childrenData)) {
this.seasonElemFreshlyLoaded = true; this.seasonElemFreshlyLoaded = true;
if (this.seasonsElem) { if (this.seasonsElem) {
this.seasonsElem.style.display = 'block'; this.seasonsElem.style.display = 'block';
@ -1433,7 +1443,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.seasonsElem.style.top = `${top + 2000}px`; this.seasonsElem.style.top = `${top + 2000}px`;
} }
_.forEach(seasonsData, seasonData => { _.forEach(childrenData, childData => {
if (this.seasonsElem && this.plex) { if (this.seasonsElem && this.plex) {
this.seasonsElemHidden = false; this.seasonsElemHidden = false;
const seasonContainer = document.createElement('div'); const seasonContainer = document.createElement('div');
@ -1441,25 +1451,30 @@ class PlexMeetsHomeAssistant extends HTMLElement {
seasonContainer.style.width = `${CSS_STYLE.width}px`; seasonContainer.style.width = `${CSS_STYLE.width}px`;
const thumbURL = `${this.plex.getBasicURL()}/photo/:/transcode?width=${this.minExpandedWidth}&height=${ const thumbURL = `${this.plex.getBasicURL()}/photo/:/transcode?width=${this.minExpandedWidth}&height=${
this.minExpandedHeight this.minExpandedHeight
}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; }&minSize=1&upscale=1&url=${childData.thumb}&X-Plex-Token=${this.config.token}`;
const seasonElem = document.createElement('div'); const seasonElem = document.createElement('div');
seasonElem.className = 'seasonElem'; seasonElem.className = 'seasonElem';
seasonElem.style.width = `${CSS_STYLE.width}px`; seasonElem.style.width = `${CSS_STYLE.width}px`;
seasonElem.style.height = `${CSS_STYLE.height - 3}px`; if (_.isEqual(childData.type, 'album')) {
seasonElem.style.height = `${CSS_STYLE.width}px`;
} else {
seasonElem.style.height = `${CSS_STYLE.height - 3}px`;
}
seasonElem.style.backgroundImage = `url('${thumbURL}')`; seasonElem.style.backgroundImage = `url('${thumbURL}')`;
seasonElem.dataset.clicked = 'false'; seasonElem.dataset.clicked = 'false';
if (this.playController && !this.playController.isPlaySupported(seasonData)) { if (this.playController && !this.playController.isPlaySupported(childData)) {
seasonElem.style.cursor = 'pointer'; seasonElem.style.cursor = 'pointer';
} }
const interactiveArea = document.createElement('div'); const interactiveArea = document.createElement('div');
interactiveArea.className = 'interactiveArea'; interactiveArea.className = 'interactiveArea';
if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { if (childData.leafCount - childData.viewedLeafCount > 0) {
const toViewElem = document.createElement('div'); const toViewElem = document.createElement('div');
toViewElem.className = 'toViewSeason'; toViewElem.className = 'toViewSeason';
toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString();
toViewElem.style.fontSize = `${this.fontSize4}px`; toViewElem.style.fontSize = `${this.fontSize4}px`;
toViewElem.style.lineHeight = `${this.fontSize4}px`; toViewElem.style.lineHeight = `${this.fontSize4}px`;
@ -1469,14 +1484,14 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
if (this.playController) { if (this.playController) {
const playButton = this.playController.getPlayButton(seasonData.type); const playButton = this.playController.getPlayButton(childData.type);
if (this.playController.isPlaySupported(seasonData)) { if (this.playController.isPlaySupported(childData)) {
playButton.classList.remove('disabled'); playButton.classList.remove('disabled');
} }
playButton.addEventListener('click', event => { playButton.addEventListener('click', event => {
event.stopPropagation(); event.stopPropagation();
if (this.plex && this.playController) { if (this.plex && this.playController) {
this.playController.play(seasonData, true); this.playController.play(childData, true);
} }
}); });
@ -1488,14 +1503,19 @@ class PlexMeetsHomeAssistant extends HTMLElement {
const seasonTitleElem = document.createElement('div'); const seasonTitleElem = document.createElement('div');
seasonTitleElem.className = 'seasonTitleElem'; seasonTitleElem.className = 'seasonTitleElem';
seasonTitleElem.innerHTML = escapeHtml(seasonData.title); seasonTitleElem.innerHTML = escapeHtml(childData.title);
seasonTitleElem.style.fontSize = `${this.fontSize1}px`; seasonTitleElem.style.fontSize = `${this.fontSize1}px`;
seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; seasonTitleElem.style.lineHeight = `${this.fontSize1}px`;
seasonContainer.append(seasonTitleElem); seasonContainer.append(seasonTitleElem);
const seasonEpisodesCount = document.createElement('div'); const seasonEpisodesCount = document.createElement('div');
seasonEpisodesCount.className = 'seasonEpisodesCount'; seasonEpisodesCount.className = 'seasonEpisodesCount';
seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; if (childData.leafCount > 0) {
seasonEpisodesCount.innerHTML = `${escapeHtml(childData.leafCount)} episodes`;
} else if (!_.isNil(childData.year)) {
seasonEpisodesCount.innerHTML = `${escapeHtml(childData.year)} `;
}
seasonEpisodesCount.style.fontSize = `${this.fontSize2}px`; seasonEpisodesCount.style.fontSize = `${this.fontSize2}px`;
seasonEpisodesCount.style.lineHeight = `${this.fontSize2}px`; seasonEpisodesCount.style.lineHeight = `${this.fontSize2}px`;
seasonContainer.append(seasonEpisodesCount); seasonContainer.append(seasonEpisodesCount);
@ -1510,12 +1530,12 @@ class PlexMeetsHomeAssistant extends HTMLElement {
if (this.activeMovieElem) { if (this.activeMovieElem) {
if (seasonElem.dataset.clicked === 'false') { if (seasonElem.dataset.clicked === 'false') {
if (this.playController) { if (this.playController) {
this.playController.setPlayActionButtonType(seasonData.type); this.playController.setPlayActionButtonType(childData.type);
this.playController.setPlayButtonClickFunction((thisEvent: MouseEvent) => { this.playController.setPlayButtonClickFunction((thisEvent: MouseEvent) => {
thisEvent.preventDefault(); thisEvent.preventDefault();
thisEvent.stopPropagation(); thisEvent.stopPropagation();
if (this.playController) { if (this.playController) {
this.playController.play(seasonData, true); this.playController.play(childData, true);
} }
}); });
} }
@ -1533,9 +1553,19 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.scrollDownInactiveSeasons(); this.scrollDownInactiveSeasons();
seasonContainer.style.top = `${-this.minExpandedHeight}px`; if (this.activeMovieElem) {
seasonContainer.style.top = `${-getHeight(this.activeMovieElem)}px`;
} else {
seasonContainer.style.top = `${-this.minExpandedHeight}px`;
}
seasonElem.dataset.type = childData.type;
seasonElem.style.width = `${this.minExpandedWidth}px`; seasonElem.style.width = `${this.minExpandedWidth}px`;
seasonElem.style.height = `${this.minExpandedHeight - 6}px`; if (_.isEqual(childData.type, 'album')) {
seasonElem.style.height = `${this.minExpandedWidth}px`;
} else {
seasonElem.style.height = `${this.minExpandedHeight - 6}px`;
}
seasonElem.style.zIndex = '3'; seasonElem.style.zIndex = '3';
seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - seasonElem.style.marginLeft = `-${getOffset(seasonElem).left -
@ -1545,36 +1575,63 @@ class PlexMeetsHomeAssistant extends HTMLElement {
seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; seasonEpisodesCount.style.color = 'rgba(255,255,255,0)';
if (this.detailElem) { if (this.detailElem) {
(this.detailElem.children[1] as HTMLElement).innerHTML = seasonData.title; (this.detailElem.children[1] as HTMLElement).innerHTML = childData.title;
} }
(async (): Promise<void> => { (async (): Promise<void> => {
if (seasonData.leafCount > 0 && this.plex) { if (this.plex && (childData.leafCount > 0 || _.isEqual(childData.type, 'album'))) {
this.episodesElemFreshlyLoaded = true; this.episodesElemFreshlyLoaded = true;
const episodesData = await this.plex.getLibraryData(seasonData.key.split('/')[3]); const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]);
if (this.episodesElem) { if (this.episodesElem) {
this.episodesElemHidden = false; this.episodesElemHidden = false;
this.episodesElem.style.display = 'block'; this.episodesElem.style.display = 'block';
this.episodesElem.innerHTML = ''; this.episodesElem.innerHTML = '';
this.episodesElem.style.transition = `0s`; this.episodesElem.style.transition = `0s`;
this.episodesElem.style.top = `${top + 2000}px`; this.episodesElem.style.top = `${top + 2000}px`;
const tableView = document.createElement('table');
tableView.style.width = 'calc(100% - 10px)';
tableView.style.border = 'none';
tableView.cellSpacing = '0';
tableView.cellPadding = '0';
if (_.isEqual(childData.type, 'album')) {
this.episodesElem.append(tableView);
}
let isEven = false;
_.forEach(episodesData, episodeData => { _.forEach(episodesData, episodeData => {
if (this.episodesElem && this.playController && this.plex) { if (this.episodesElem && this.playController && this.plex) {
this.episodesElem.append( if (_.isEqual(episodeData.type, 'track')) {
createEpisodesView( tableView.append(
this.playController, createTrackView(
this.plex, this.playController,
episodeData, this.plex,
this.fontSize1, episodeData,
this.fontSize2 this.fontSize1,
) this.fontSize2,
); isEven
)
);
isEven = !isEven;
} else {
this.episodesElem.append(
createEpisodesView(
this.playController,
this.plex,
episodeData,
this.fontSize1,
this.fontSize2
)
);
}
} }
}); });
clearInterval(this.episodesLoadTimeout); clearInterval(this.episodesLoadTimeout);
this.episodesLoadTimeout = setTimeout(() => { this.episodesLoadTimeout = setTimeout(() => {
if (this.episodesElem) { if (this.episodesElem) {
this.episodesElem.style.transition = `0.7s`; this.episodesElem.style.transition = `0.7s`;
this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; if (this.activeMovieElem) {
this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`;
} else {
this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`;
}
this.resizeBackground(); this.resizeBackground();
} }
@ -1589,7 +1646,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} else { } else {
// todo: change title from season and change media type of play button back // todo: change title from season and change media type of play button back
if (this.playController) { if (this.playController) {
this.playController.setPlayActionButtonType(seasonData.type); this.playController.setPlayActionButtonType(childData.type);
} }
seasonContainer.style.top = `${seasonContainer.dataset.top}px`; seasonContainer.style.top = `${seasonContainer.dataset.top}px`;
this.minimizeSeasons(); this.minimizeSeasons();
@ -1639,7 +1696,11 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.showSeasonElemTimeout = setTimeout(() => { this.showSeasonElemTimeout = setTimeout(() => {
if (this.seasonsElem) { if (this.seasonsElem) {
this.seasonsElem.style.transition = `0.7s`; this.seasonsElem.style.transition = `0.7s`;
this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`; if (this.activeMovieElem) {
this.seasonsElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`;
} else {
this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`;
}
this.resizeBackground(); this.resizeBackground();
} }
@ -1815,8 +1876,10 @@ class PlexMeetsHomeAssistant extends HTMLElement {
movieElem.style.width = `${CSS_STYLE.width}px`; movieElem.style.width = `${CSS_STYLE.width}px`;
movieElem.style.height = `${CSS_STYLE.height}px`; movieElem.style.height = `${CSS_STYLE.height}px`;
if (!_.isNil(data.channelCallSign)) { if (!_.isNil(data.channelCallSign) || _.isEqual(data.type, 'artist')) {
movieElem.style.backgroundSize = '80%'; if (!_.isEqual(data.type, 'artist')) {
movieElem.style.backgroundSize = '80%';
}
movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)'; movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)';
movieElem.style.backgroundPosition = 'center'; movieElem.style.backgroundPosition = 'center';
movieElem.style.height = `${CSS_STYLE.width}px`; movieElem.style.height = `${CSS_STYLE.width}px`;

Loading…
Cancel
Save