diff --git a/dist/plex-meets-homeassistant.js b/dist/plex-meets-homeassistant.js index f37454b..9834204 100644 --- a/dist/plex-meets-homeassistant.js +++ b/dist/plex-meets-homeassistant.js @@ -18815,8 +18815,8 @@ class Plex { }); return lodash.isNil(collectionsData.data.MediaContainer.Metadata) ? [] : collectionsData.data.MediaContainer.Metadata; }; - this.getSectionData = async (sectionID) => { - return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]); + this.getSectionData = async (sectionID, type = false) => { + return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID, type)]); }; this.getChildren = async (childrenURL) => { const bulkItems = 50; @@ -18861,10 +18861,14 @@ class Plex { this.getPlaylistData = async (playlistKey) => { return this.getChildren(playlistKey); }; - this.getSectionDataWithoutProcessing = async (sectionID) => { + this.getSectionDataWithoutProcessing = async (sectionID, type = false) => { const bulkItems = 50; let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`); url += `&sort=${this.sort}`; + if (type) { + url += `&type=${type}`; + } + url += `&includeCollections=1&includeExternalMedia=1&includeAdvanced=1&includeMeta=1`; let result = {}; try { result = await axios.get(url, { @@ -20158,6 +20162,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.protocol = document.createElement('paper-dropdown-menu'); this.tabs = document.createElement('paper-tabs'); this.sort = document.createElement('paper-dropdown-menu'); + this.displayType = document.createElement('paper-dropdown-menu'); this.sortOrder = document.createElement('paper-dropdown-menu'); this.playTrailer = document.createElement('paper-dropdown-menu'); this.showExtras = document.createElement('paper-dropdown-menu'); @@ -20213,6 +20218,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { else { this.config.sort = ``; } + this.config.displayType = this.displayType.value; if (lodash.isEmpty(this.maxCount.value)) { this.config.maxCount = ''; } @@ -20335,10 +20341,14 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { } }; this.render = async () => { - const addDropdownItem = (text, disabled = false) => { + const addDropdownItem = (value, text = '', disabled = false) => { + if (lodash.isEmpty(text)) { + // eslint-disable-next-line no-param-reassign + text = value; + } const libraryItem = document.createElement('paper-item'); libraryItem.innerHTML = text.replace(/ /g, ' '); - libraryItem.label = text; + libraryItem.label = value; if (disabled) { libraryItem.disabled = true; } @@ -20448,7 +20458,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.content.appendChild(this.token); this.libraryName.innerHTML = ''; const libraryItems = document.createElement('paper-listbox'); - libraryItems.appendChild(addDropdownItem('Smart Libraries', true)); + libraryItems.appendChild(addDropdownItem('Smart Libraries', '', true)); libraryItems.appendChild(addDropdownItem('Continue Watching')); libraryItems.appendChild(addDropdownItem('Deck')); libraryItems.appendChild(addDropdownItem('Recently Added')); @@ -20554,6 +20564,14 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { viewTitle.style.marginBottom = '0px'; viewTitle.style.marginTop = '20px'; this.plexValidSection.appendChild(viewTitle); + this.displayType.innerHTML = ''; + const typeItems = document.createElement('paper-listbox'); + typeItems.slot = 'dropdown-content'; + this.displayType.label = 'Display Type (Optional)'; + this.displayType.appendChild(typeItems); + this.displayType.style.width = '100%'; + this.displayType.addEventListener('value-changed', this.valueUpdated); + this.plexValidSection.appendChild(this.displayType); this.cardTitle.label = 'Card title (Optional)'; this.cardTitle.value = this.config.title; this.cardTitle.addEventListener('change', this.valueUpdated); @@ -20772,7 +20790,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.fontSize4.addEventListener('change', this.valueUpdated); this.plexValidSection.appendChild(this.fontSize4); if (!lodash.isEmpty(this.livetv)) { - libraryItems.appendChild(addDropdownItem('Live TV', true)); + libraryItems.appendChild(addDropdownItem('Live TV', '', true)); lodash.forEach(lodash.keys(this.livetv), (livetv) => { if (lodash.isEqual(this.config.libraryName, livetv)) { warningLibrary.innerHTML = `Warning: ${this.config.libraryName} play action currently only supported with Kodi.
You might also need custom build of kodi-media-sensors, see detailed configuration for more information.`; @@ -20781,66 +20799,96 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { }); } if (!lodash.isEmpty(this.sections)) { - libraryItems.appendChild(addDropdownItem('Libraries', true)); + libraryItems.appendChild(addDropdownItem('Libraries', '', true)); lodash.forEach(this.sections, (section) => { libraryItems.appendChild(addDropdownItem(section.title)); }); if (!lodash.isEmpty(this.collections)) { - libraryItems.appendChild(addDropdownItem('Collections', true)); + libraryItems.appendChild(addDropdownItem('Collections', '', true)); lodash.forEach(this.collections, (collection) => { libraryItems.appendChild(addDropdownItem(collection.title)); }); } if (!lodash.isEmpty(this.playlists)) { - libraryItems.appendChild(addDropdownItem('Playlists', true)); + libraryItems.appendChild(addDropdownItem('Playlists', '', true)); lodash.forEach(this.playlists, (playlist) => { libraryItems.appendChild(addDropdownItem(playlist.title)); }); } this.libraryName.disabled = false; this.libraryName.value = this.config.libraryName; - let libraryType = ''; + let libraryKey = ''; // eslint-disable-next-line consistent-return lodash.forEach(this.sections, section => { if (lodash.isEqual(section.title, this.libraryName.value)) { - libraryType = section.type; + libraryKey = section.key; return false; } }); - if (lodash.isEqual(libraryType, 'show')) { - sortItems.appendChild(addDropdownItem('titleSort')); - sortItems.appendChild(addDropdownItem('title')); - sortItems.appendChild(addDropdownItem('year')); - sortItems.appendChild(addDropdownItem('originallyAvailableAt')); - sortItems.appendChild(addDropdownItem('rating')); - sortItems.appendChild(addDropdownItem('audienceRating')); - sortItems.appendChild(addDropdownItem('userRating')); - sortItems.appendChild(addDropdownItem('contentRating')); - sortItems.appendChild(addDropdownItem('unviewedLeafCount')); - sortItems.appendChild(addDropdownItem('episode.addedAt')); - sortItems.appendChild(addDropdownItem('addedAt')); - sortItems.appendChild(addDropdownItem('lastViewedAt')); - this.sort.style.display = 'block'; - this.sortOrder.style.display = 'block'; - } - else if (lodash.isEqual(libraryType, 'movie')) { - sortItems.appendChild(addDropdownItem('titleSort')); - sortItems.appendChild(addDropdownItem('title')); - sortItems.appendChild(addDropdownItem('originallyAvailableAt')); - sortItems.appendChild(addDropdownItem('rating')); - sortItems.appendChild(addDropdownItem('audienceRating')); - sortItems.appendChild(addDropdownItem('userRating')); - sortItems.appendChild(addDropdownItem('duration')); - sortItems.appendChild(addDropdownItem('viewOffset')); - sortItems.appendChild(addDropdownItem('viewCount')); - sortItems.appendChild(addDropdownItem('addedAt')); - sortItems.appendChild(addDropdownItem('lastViewedAt')); - sortItems.appendChild(addDropdownItem('mediaHeight')); - sortItems.appendChild(addDropdownItem('mediaBitrate')); - this.sort.style.display = 'block'; - this.sortOrder.style.display = 'block'; + if (!lodash.isEmpty(libraryKey)) { + const libraryData = await this.plex.getSectionData(libraryKey); + const types = lodash.get(libraryData, '[0].Meta.Type'); + if (!lodash.isNil(types) && types.length > 1) { + let addedTypes = 0; + typeItems.appendChild(addDropdownItem('', '')); + let typeAvailable = false; + lodash.forEach(types, (sectionType) => { + if (sectionType.type !== 'folder' && sectionType.type !== 'track' && sectionType.type !== 'episode') { + const key = sectionType.key.split('type=')[1]; + if (lodash.isEqual(key, this.config.displayType)) { + typeAvailable = true; + } + typeItems.appendChild(addDropdownItem(key, sectionType.title)); + addedTypes += 1; + } + }); + if (addedTypes > 1) { + this.displayType.style.display = 'block'; + if (lodash.isEmpty(this.config.displayType) || !typeAvailable) { + this.displayType.value = ''; + } + else { + this.displayType.value = this.config.displayType; + } + } + else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; + } + } + else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; + } + let displayTypeIndex = 0; + if (this.config.displayType) { + lodash.forEach(types, (sectionType, sectionKey) => { + const key = sectionType.key.split('type=')[1]; + if (key === parseInt(this.config.displayType, 10)) { + displayTypeIndex = parseInt(sectionKey, 10); + } + }); + } + const sortFields = lodash.get(libraryData, `[0].Meta.Type[${displayTypeIndex}].Sort`); + if (!lodash.isNil(sortFields) && sortFields.length > 0) { + lodash.forEach(sortFields, (sortField) => { + sortItems.appendChild(addDropdownItem(sortField.key)); + }); + this.sort.style.display = 'block'; + this.sortOrder.style.display = 'block'; + } + else { + this.sort.style.display = 'none'; + this.sortOrder.style.display = 'none'; + this.config.sort = ''; + } } else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; this.sort.style.display = 'none'; this.sortOrder.style.display = 'none'; this.config.sort = ''; @@ -20890,6 +20938,9 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { if (!config.sort) { this.config.sort = 'titleSort:asc'; } + if (!config.displayType) { + this.config.displayType = ''; + } if (!lodash.isNil(config.playTrailer)) { this.config.playTrailer = config.playTrailer; } @@ -21777,6 +21828,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { this.renderPageRetries = 0; this.searchInputElem = document.createElement('input'); this.plexProtocol = 'http'; + this.displayType = false; this.useHorizontalScroll = false; this.displayTitleMain = true; this.displaySubtitleMain = true; @@ -22096,7 +22148,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { this.epgData = await this.plex.getEPG(); } }; - let sectionKey = 0; + let sectionKey = false; lodash.forEach(plexAllSections, (section) => { if (lodash.isEqual(section.title, this.config.libraryName)) { sectionKey = section.key; @@ -22106,7 +22158,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { }); const loadDataRequests = []; if (sectionKey) { - loadDataRequests.push(this.plex.getSectionData(sectionKey)); + loadDataRequests.push(this.plex.getSectionData(sectionKey, this.displayType)); } if (lodash.isEqual(this.config.libraryName, 'Deck')) { loadDataRequests.push(getOnDeck()); @@ -22897,7 +22949,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { if (lodash.isEqual(data.type, 'episode')) { childrenData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]); } - else if (data.childCount > 0 || lodash.isEqual(data.type, 'artist')) { + else if (data.childCount > 0 || lodash.isEqual(data.type, 'artist') || lodash.isEqual(data.type, 'album')) { childrenData = await this.plex.getLibraryData(data.key.split('/')[3]); } let dataDetails = {}; @@ -23010,230 +23062,279 @@ class PlexMeetsHomeAssistant extends HTMLElement { this.seasonsElem.style.transition = `0s`; this.seasonsElem.style.top = `${top + 2000}px`; } - lodash.forEach(childrenData, childData => { - if (this.seasonsElem && this.plex) { - this.seasonsElemHidden = false; - const seasonContainer = document.createElement('div'); - seasonContainer.className = 'seasonContainer'; - 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=${childData.thumb}&X-Plex-Token=${this.config.token}`; - const seasonElem = document.createElement('div'); - seasonElem.className = 'seasonElem'; - seasonElem.style.width = `${CSS_STYLE.width}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.dataset.clicked = 'false'; - if (this.playController && !this.playController.isPlaySupported(childData)) { - seasonElem.style.cursor = 'pointer'; + if (lodash.isEqual(lodash.get(childrenData[0], 'type'), 'track')) { + if (this.episodesElem) { + this.episodesElemHidden = false; + this.episodesElem.style.display = 'block'; + this.episodesElem.innerHTML = ''; + this.episodesElem.style.transition = `0s`; + 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(data.type, 'album')) { + this.episodesElem.append(tableView); } - const interactiveArea = document.createElement('div'); - interactiveArea.className = 'interactiveArea'; - if (childData.leafCount - childData.viewedLeafCount > 0) { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewSeason'; - toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString(); - toViewElem.style.fontSize = `${this.fontSize4}px`; - toViewElem.style.lineHeight = `${this.fontSize4}px`; - toViewElem.style.padding = `${this.fontSize4 / 2}px`; - interactiveArea.appendChild(toViewElem); - } - if (this.playController) { - const playButton = this.playController.getPlayButton(childData.type); - if (this.playController.isPlaySupported(childData)) { - playButton.classList.remove('disabled'); - } - playButton.addEventListener('click', event => { - event.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(childData, true); + let isEven = false; + lodash.forEach(childrenData, childData => { + if (this.episodesElem && this.playController && this.plex) { + if (lodash.isEqual(childData.type, 'track')) { + tableView.append(createTrackView(this.playController, this.plex, childData, this.fontSize1, this.fontSize2, isEven)); + isEven = !isEven; } - }); - interactiveArea.append(playButton); - } - seasonElem.append(interactiveArea); - seasonContainer.append(seasonElem); - const seasonTitleElem = document.createElement('div'); - seasonTitleElem.className = 'seasonTitleElem'; - seasonTitleElem.innerHTML = escapeHtml(childData.title); - seasonTitleElem.style.fontSize = `${this.fontSize1}px`; - seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; - seasonContainer.append(seasonTitleElem); - const seasonEpisodesCount = document.createElement('div'); - seasonEpisodesCount.className = 'seasonEpisodesCount'; - 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.lineHeight = `${this.fontSize2}px`; - seasonContainer.append(seasonEpisodesCount); - seasonContainer.addEventListener('click', event => { - event.stopPropagation(); - if (this.seasonContainerClickEnabled) { - this.seasonContainerClickEnabled = false; - setTimeout(() => { - this.seasonContainerClickEnabled = true; - }, 500); + else { + this.episodesElem.append(createEpisodesView(this.playController, this.plex, childData, this.fontSize1, this.fontSize2)); + } + } + }); + clearInterval(this.episodesLoadTimeout); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; if (this.activeMovieElem) { - if (seasonElem.dataset.clicked === 'false') { - if (this.playController) { - this.playController.setPlayActionButtonType(childData.type); - this.playController.setPlayButtonClickFunction((thisEvent) => { - thisEvent.preventDefault(); - thisEvent.stopPropagation(); - if (this.playController) { - this.playController.play(childData, true); + this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; + } + else { + this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; + } + this.resizeBackground(); + } + }, 200); + clearInterval(this.episodesElemFreshlyLoadedTimeout); + this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { + this.episodesElemFreshlyLoaded = false; + }, 700); + } + } + else { + lodash.forEach(childrenData, childData => { + if (this.seasonsElem && this.plex) { + console.log(childData); + this.seasonsElemHidden = false; + const seasonContainer = document.createElement('div'); + seasonContainer.className = 'seasonContainer'; + 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=${childData.thumb}&X-Plex-Token=${this.config.token}`; + const seasonElem = document.createElement('div'); + seasonElem.className = 'seasonElem'; + seasonElem.style.width = `${CSS_STYLE.width}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.dataset.clicked = 'false'; + if (this.playController && !this.playController.isPlaySupported(childData)) { + seasonElem.style.cursor = 'pointer'; + } + const interactiveArea = document.createElement('div'); + interactiveArea.className = 'interactiveArea'; + if (childData.leafCount - childData.viewedLeafCount > 0) { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewSeason'; + toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString(); + toViewElem.style.fontSize = `${this.fontSize4}px`; + toViewElem.style.lineHeight = `${this.fontSize4}px`; + toViewElem.style.padding = `${this.fontSize4 / 2}px`; + interactiveArea.appendChild(toViewElem); + } + if (this.playController) { + const playButton = this.playController.getPlayButton(childData.type); + if (this.playController.isPlaySupported(childData)) { + playButton.classList.remove('disabled'); + } + playButton.addEventListener('click', event => { + event.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(childData, true); + } + }); + interactiveArea.append(playButton); + } + seasonElem.append(interactiveArea); + seasonContainer.append(seasonElem); + const seasonTitleElem = document.createElement('div'); + seasonTitleElem.className = 'seasonTitleElem'; + seasonTitleElem.innerHTML = escapeHtml(childData.title); + seasonTitleElem.style.fontSize = `${this.fontSize1}px`; + seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; + seasonContainer.append(seasonTitleElem); + const seasonEpisodesCount = document.createElement('div'); + seasonEpisodesCount.className = 'seasonEpisodesCount'; + 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.lineHeight = `${this.fontSize2}px`; + seasonContainer.append(seasonEpisodesCount); + seasonContainer.addEventListener('click', event => { + event.stopPropagation(); + if (this.seasonContainerClickEnabled) { + this.seasonContainerClickEnabled = false; + setTimeout(() => { + this.seasonContainerClickEnabled = true; + }, 500); + if (this.activeMovieElem) { + if (seasonElem.dataset.clicked === 'false') { + if (this.playController) { + this.playController.setPlayActionButtonType(childData.type); + this.playController.setPlayButtonClickFunction((thisEvent) => { + thisEvent.preventDefault(); + thisEvent.stopPropagation(); + if (this.playController) { + this.playController.play(childData, true); + } + }); + } + if (typeof seasonElem.children[0].children[0] !== 'undefined') { + seasonElem.children[0].children[0].style.display = 'none'; + } + seasonElem.dataset.clicked = 'true'; + this.activeMovieElem.style.top = `${top - 1000}px`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.display = 'none'; } - }); - } - if (typeof seasonElem.children[0].children[0] !== 'undefined') { - seasonElem.children[0].children[0].style.display = 'none'; - } - seasonElem.dataset.clicked = 'true'; - this.activeMovieElem.style.top = `${top - 1000}px`; - setTimeout(() => { + }, 500); + this.scrollDownInactiveSeasons(); if (this.activeMovieElem) { - this.activeMovieElem.style.display = 'none'; + seasonContainer.style.top = `${-getHeight(this.activeMovieElem)}px`; } - }, 500); - this.scrollDownInactiveSeasons(); - 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`; - 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.marginLeft = `-${getOffset(seasonElem).left - - getOffset(this.activeMovieElem).left}px`; - seasonTitleElem.style.color = 'rgba(255,255,255,0)'; - seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; - if (this.detailElem) { - this.detailElem.children[1].innerHTML = childData.title; - } - (async () => { - if (this.plex && (childData.leafCount > 0 || lodash.isEqual(childData.type, 'album'))) { - this.episodesElemFreshlyLoaded = true; - const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]); - if (this.episodesElem) { - this.episodesElemHidden = false; - this.episodesElem.style.display = 'block'; - this.episodesElem.innerHTML = ''; - this.episodesElem.style.transition = `0s`; - 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 => { - if (this.episodesElem && this.playController && this.plex) { - 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)); - } + else { + seasonContainer.style.top = `${-this.minExpandedHeight}px`; + } + seasonElem.dataset.type = childData.type; + seasonElem.style.width = `${this.minExpandedWidth}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.marginLeft = `-${getOffset(seasonElem).left - + getOffset(this.activeMovieElem).left}px`; + seasonTitleElem.style.color = 'rgba(255,255,255,0)'; + seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; + if (this.detailElem) { + this.detailElem.children[1].innerHTML = childData.title; + } + (async () => { + if (this.plex && (childData.leafCount > 0 || lodash.isEqual(childData.type, 'album'))) { + this.episodesElemFreshlyLoaded = true; + const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]); + if (this.episodesElem) { + this.episodesElemHidden = false; + this.episodesElem.style.display = 'block'; + this.episodesElem.innerHTML = ''; + this.episodesElem.style.transition = `0s`; + 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); } - }); - clearInterval(this.episodesLoadTimeout); - this.episodesLoadTimeout = setTimeout(() => { - if (this.episodesElem) { - this.episodesElem.style.transition = `0.7s`; - if (this.activeMovieElem) { - this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; + let isEven = false; + lodash.forEach(episodesData, episodeData => { + if (this.episodesElem && this.playController && this.plex) { + 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)); + } } - else { - this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; + }); + clearInterval(this.episodesLoadTimeout); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; + 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); - clearInterval(this.episodesElemFreshlyLoadedTimeout); - this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { - this.episodesElemFreshlyLoaded = false; - }, 700); + }, 200); + clearInterval(this.episodesElemFreshlyLoadedTimeout); + this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { + this.episodesElemFreshlyLoaded = false; + }, 700); + } } - } - })(); - } - else { - // todo: change title from season and change media type of play button back - if (this.playController) { - this.playController.setPlayActionButtonType(childData.type); + })(); } - seasonContainer.style.top = `${seasonContainer.dataset.top}px`; - this.minimizeSeasons(); - this.hideEpisodes(); - this.activeMovieElem.style.display = `block`; - setTimeout(() => { - if (this.activeMovieElem) { - this.activeMovieElem.style.top = `${top + 16}px`; + else { + // todo: change title from season and change media type of play button back + if (this.playController) { + this.playController.setPlayActionButtonType(childData.type); } - }, 10); - if (this.detailElem && this.detailElem.children[1]) { - const { year } = this.detailElem.children[1].dataset; - if (year) { - this.detailElem.children[1].innerHTML = year; + seasonContainer.style.top = `${seasonContainer.dataset.top}px`; + this.minimizeSeasons(); + this.hideEpisodes(); + this.activeMovieElem.style.display = `block`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.top = `${top + 16}px`; + } + }, 10); + if (this.detailElem && this.detailElem.children[1]) { + const { year } = this.detailElem.children[1].dataset; + if (year) { + this.detailElem.children[1].innerHTML = year; + } } } } } - } - }); - this.seasonsElem.append(seasonContainer); - } - }); - lodash.forEach(this.seasonsElem.children, elem => { - const seasonElem = elem; - const left = seasonElem.offsetLeft; - const topElem = seasonElem.offsetTop; - seasonElem.style.left = `${left}px`; - seasonElem.dataset.left = `${left}`; - seasonElem.style.top = `${topElem}px`; - seasonElem.dataset.top = `${topElem}`; - }); - lodash.forEach(this.seasonsElem.children, elem => { - const seasonElem = elem; - seasonElem.style.position = 'absolute'; - }); - clearInterval(this.seasonElemFreshlyLoadedTimeout); - this.seasonElemFreshlyLoadedTimeout = setTimeout(() => { - this.seasonElemFreshlyLoaded = false; - }, 700); - clearInterval(this.showSeasonElemTimeout); - this.showSeasonElemTimeout = setTimeout(() => { - if (this.seasonsElem) { - this.seasonsElem.style.transition = `0.7s`; - if (this.activeMovieElem) { - this.seasonsElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; + }); + this.seasonsElem.append(seasonContainer); } - else { - this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`; + }); + lodash.forEach(this.seasonsElem.children, elem => { + const seasonElem = elem; + const left = seasonElem.offsetLeft; + const topElem = seasonElem.offsetTop; + seasonElem.style.left = `${left}px`; + seasonElem.dataset.left = `${left}`; + seasonElem.style.top = `${topElem}px`; + seasonElem.dataset.top = `${topElem}`; + }); + lodash.forEach(this.seasonsElem.children, elem => { + const seasonElem = elem; + seasonElem.style.position = 'absolute'; + }); + clearInterval(this.seasonElemFreshlyLoadedTimeout); + this.seasonElemFreshlyLoadedTimeout = setTimeout(() => { + this.seasonElemFreshlyLoaded = false; + }, 700); + clearInterval(this.showSeasonElemTimeout); + this.showSeasonElemTimeout = setTimeout(() => { + if (this.seasonsElem) { + this.seasonsElem.style.transition = `0.7s`; + 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); + } } else { this.episodesElemFreshlyLoaded = true; @@ -23384,8 +23485,8 @@ class PlexMeetsHomeAssistant extends HTMLElement { movieElem.className = 'movieElem'; movieElem.style.width = `${CSS_STYLE.width}px`; movieElem.style.height = `${CSS_STYLE.height}px`; - if (!lodash.isNil(data.channelCallSign) || lodash.isEqual(data.type, 'artist')) { - if (!lodash.isEqual(data.type, 'artist')) { + if (!lodash.isNil(data.channelCallSign) || lodash.isEqual(data.type, 'artist') || lodash.isEqual(data.type, 'album')) { + if (!lodash.isEqual(data.type, 'artist') && !lodash.isEqual(data.type, 'album')) { movieElem.style.backgroundSize = '80%'; } movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)'; @@ -23536,6 +23637,9 @@ class PlexMeetsHomeAssistant extends HTMLElement { if (config.protocol) { this.plexProtocol = config.protocol; } + if (config.displayType && !lodash.isEmpty(config.displayType)) { + this.displayType = config.displayType; + } if (config.useHorizontalScroll && lodash.isEqual(config.useHorizontalScroll, 'Yes')) { this.useHorizontalScroll = true; } diff --git a/src/editor.ts b/src/editor.ts index 1510109..1870811 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -58,6 +58,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { sort: any = document.createElement('paper-dropdown-menu'); + displayType: any = document.createElement('paper-dropdown-menu'); + sortOrder: any = document.createElement('paper-dropdown-menu'); playTrailer: any = document.createElement('paper-dropdown-menu'); @@ -139,6 +141,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.config.sort = ``; } + this.config.displayType = this.displayType.value; + if (_.isEmpty(this.maxCount.value)) { this.config.maxCount = ''; } else { @@ -258,10 +262,14 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { }; render = async (): Promise => { - const addDropdownItem = (text: string, disabled = false): HTMLElement => { + const addDropdownItem = (value: string, text = '', disabled = false): HTMLElement => { + if (_.isEmpty(text)) { + // eslint-disable-next-line no-param-reassign + text = value; + } const libraryItem: any = document.createElement('paper-item'); libraryItem.innerHTML = text.replace(/ /g, ' '); - libraryItem.label = text; + libraryItem.label = value; if (disabled) { libraryItem.disabled = true; } @@ -381,7 +389,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.libraryName.innerHTML = ''; const libraryItems: any = document.createElement('paper-listbox'); - libraryItems.appendChild(addDropdownItem('Smart Libraries', true)); + libraryItems.appendChild(addDropdownItem('Smart Libraries', '', true)); libraryItems.appendChild(addDropdownItem('Continue Watching')); libraryItems.appendChild(addDropdownItem('Deck')); libraryItems.appendChild(addDropdownItem('Recently Added')); @@ -396,6 +404,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { const warningLibrary = document.createElement('div'); warningLibrary.style.color = 'red'; this.content.appendChild(this.libraryName); + this.content.appendChild(warningLibrary); this.appendChild(this.content); @@ -500,6 +509,15 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { viewTitle.style.marginTop = '20px'; this.plexValidSection.appendChild(viewTitle); + this.displayType.innerHTML = ''; + const typeItems: any = document.createElement('paper-listbox'); + typeItems.slot = 'dropdown-content'; + this.displayType.label = 'Display Type (Optional)'; + this.displayType.appendChild(typeItems); + this.displayType.style.width = '100%'; + this.displayType.addEventListener('value-changed', this.valueUpdated); + this.plexValidSection.appendChild(this.displayType); + this.cardTitle.label = 'Card title (Optional)'; this.cardTitle.value = this.config.title; this.cardTitle.addEventListener('change', this.valueUpdated); @@ -734,7 +752,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.plexValidSection.appendChild(this.fontSize4); if (!_.isEmpty(this.livetv)) { - libraryItems.appendChild(addDropdownItem('Live TV', true)); + libraryItems.appendChild(addDropdownItem('Live TV', '', true)); _.forEach(_.keys(this.livetv), (livetv: string) => { if (_.isEqual(this.config.libraryName, livetv)) { warningLibrary.innerHTML = `Warning: ${this.config.libraryName} play action currently only supported with Kodi.
You might also need custom build of kodi-media-sensors, see detailed configuration for more information.`; @@ -743,18 +761,18 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { }); } if (!_.isEmpty(this.sections)) { - libraryItems.appendChild(addDropdownItem('Libraries', true)); + libraryItems.appendChild(addDropdownItem('Libraries', '', true)); _.forEach(this.sections, (section: Record) => { libraryItems.appendChild(addDropdownItem(section.title)); }); if (!_.isEmpty(this.collections)) { - libraryItems.appendChild(addDropdownItem('Collections', true)); + libraryItems.appendChild(addDropdownItem('Collections', '', true)); _.forEach(this.collections, (collection: Record) => { libraryItems.appendChild(addDropdownItem(collection.title)); }); } if (!_.isEmpty(this.playlists)) { - libraryItems.appendChild(addDropdownItem('Playlists', true)); + libraryItems.appendChild(addDropdownItem('Playlists', '', true)); _.forEach(this.playlists, (playlist: Record) => { libraryItems.appendChild(addDropdownItem(playlist.title)); }); @@ -763,46 +781,75 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.libraryName.disabled = false; this.libraryName.value = this.config.libraryName; - let libraryType = ''; + let libraryKey = ''; // eslint-disable-next-line consistent-return _.forEach(this.sections, section => { if (_.isEqual(section.title, this.libraryName.value)) { - libraryType = section.type; + libraryKey = section.key; return false; } }); - if (_.isEqual(libraryType, 'show')) { - sortItems.appendChild(addDropdownItem('titleSort')); - sortItems.appendChild(addDropdownItem('title')); - sortItems.appendChild(addDropdownItem('year')); - sortItems.appendChild(addDropdownItem('originallyAvailableAt')); - sortItems.appendChild(addDropdownItem('rating')); - sortItems.appendChild(addDropdownItem('audienceRating')); - sortItems.appendChild(addDropdownItem('userRating')); - sortItems.appendChild(addDropdownItem('contentRating')); - sortItems.appendChild(addDropdownItem('unviewedLeafCount')); - sortItems.appendChild(addDropdownItem('episode.addedAt')); - sortItems.appendChild(addDropdownItem('addedAt')); - sortItems.appendChild(addDropdownItem('lastViewedAt')); - this.sort.style.display = 'block'; - this.sortOrder.style.display = 'block'; - } else if (_.isEqual(libraryType, 'movie')) { - sortItems.appendChild(addDropdownItem('titleSort')); - sortItems.appendChild(addDropdownItem('title')); - sortItems.appendChild(addDropdownItem('originallyAvailableAt')); - sortItems.appendChild(addDropdownItem('rating')); - sortItems.appendChild(addDropdownItem('audienceRating')); - sortItems.appendChild(addDropdownItem('userRating')); - sortItems.appendChild(addDropdownItem('duration')); - sortItems.appendChild(addDropdownItem('viewOffset')); - sortItems.appendChild(addDropdownItem('viewCount')); - sortItems.appendChild(addDropdownItem('addedAt')); - sortItems.appendChild(addDropdownItem('lastViewedAt')); - sortItems.appendChild(addDropdownItem('mediaHeight')); - sortItems.appendChild(addDropdownItem('mediaBitrate')); - this.sort.style.display = 'block'; - this.sortOrder.style.display = 'block'; + if (!_.isEmpty(libraryKey)) { + const libraryData = await this.plex.getSectionData(libraryKey); + const types = _.get(libraryData, '[0].Meta.Type'); + if (!_.isNil(types) && types.length > 1) { + let addedTypes = 0; + typeItems.appendChild(addDropdownItem('', '')); + let typeAvailable = false; + _.forEach(types, (sectionType: Record) => { + if (sectionType.type !== 'folder' && sectionType.type !== 'track' && sectionType.type !== 'episode') { + const key = sectionType.key.split('type=')[1]; + if (_.isEqual(key, this.config.displayType)) { + typeAvailable = true; + } + typeItems.appendChild(addDropdownItem(key, sectionType.title)); + addedTypes += 1; + } + }); + if (addedTypes > 1) { + this.displayType.style.display = 'block'; + + if (_.isEmpty(this.config.displayType) || !typeAvailable) { + this.displayType.value = ''; + } else { + this.displayType.value = this.config.displayType; + } + } else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; + } + } else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; + } + + let displayTypeIndex = 0; + if (this.config.displayType) { + _.forEach(types, (sectionType: Record, sectionKey) => { + const key = sectionType.key.split('type=')[1]; + if (key === parseInt(this.config.displayType, 10)) { + displayTypeIndex = parseInt(sectionKey, 10); + } + }); + } + const sortFields = _.get(libraryData, `[0].Meta.Type[${displayTypeIndex}].Sort`); + if (!_.isNil(sortFields) && sortFields.length > 0) { + _.forEach(sortFields, (sortField: Record) => { + sortItems.appendChild(addDropdownItem(sortField.key)); + }); + this.sort.style.display = 'block'; + this.sortOrder.style.display = 'block'; + } else { + this.sort.style.display = 'none'; + this.sortOrder.style.display = 'none'; + this.config.sort = ''; + } } else { + this.displayType.style.display = 'none'; + this.config.displayType = ''; + this.displayType.value = ''; this.sort.style.display = 'none'; this.sortOrder.style.display = 'none'; this.config.sort = ''; @@ -853,6 +900,10 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement { this.config.sort = 'titleSort:asc'; } + if (!config.displayType) { + this.config.displayType = ''; + } + if (!_.isNil(config.playTrailer)) { this.config.playTrailer = config.playTrailer; } else { diff --git a/src/modules/Plex.ts b/src/modules/Plex.ts index 419601e..2ca4377 100644 --- a/src/modules/Plex.ts +++ b/src/modules/Plex.ts @@ -197,8 +197,8 @@ class Plex { return _.isNil(collectionsData.data.MediaContainer.Metadata) ? [] : collectionsData.data.MediaContainer.Metadata; }; - getSectionData = async (sectionID: number): Promise => { - return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]); + getSectionData = async (sectionID: string, type: string | false = false): Promise => { + return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID, type)]); }; private getChildren = async (childrenURL: string): Promise => { @@ -257,10 +257,14 @@ class Plex { return this.getChildren(playlistKey); }; - private getSectionDataWithoutProcessing = async (sectionID: number): Promise => { + private getSectionDataWithoutProcessing = async (sectionID: string, type: string | false = false): Promise => { const bulkItems = 50; let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`); url += `&sort=${this.sort}`; + if (type) { + url += `&type=${type}`; + } + url += `&includeCollections=1&includeExternalMedia=1&includeAdvanced=1&includeMeta=1`; let result: Record = {}; try { result = await axios.get(url, { diff --git a/src/plex-meets-homeassistant.ts b/src/plex-meets-homeassistant.ts index 023b648..64a2e43 100644 --- a/src/plex-meets-homeassistant.ts +++ b/src/plex-meets-homeassistant.ts @@ -37,6 +37,8 @@ class PlexMeetsHomeAssistant extends HTMLElement { plexProtocol: 'http' | 'https' = 'http'; + displayType: string | false = false; + useHorizontalScroll = false; displayTitleMain = true; @@ -469,7 +471,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { } }; - let sectionKey: number | false = 0; + let sectionKey: string | false = false; _.forEach(plexAllSections, (section: Record) => { if (_.isEqual(section.title, this.config.libraryName)) { sectionKey = section.key; @@ -479,7 +481,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { }); const loadDataRequests = []; if (sectionKey) { - loadDataRequests.push(this.plex.getSectionData(sectionKey)); + loadDataRequests.push(this.plex.getSectionData(sectionKey, this.displayType)); } if (_.isEqual(this.config.libraryName, 'Deck')) { loadDataRequests.push(getOnDeck()); @@ -1338,7 +1340,7 @@ class PlexMeetsHomeAssistant extends HTMLElement { let childrenData: Record = {}; if (_.isEqual(data.type, 'episode')) { childrenData = await this.plex.getLibraryData(data.grandparentKey.split('/')[3]); - } else if (data.childCount > 0 || _.isEqual(data.type, 'artist')) { + } else if (data.childCount > 0 || _.isEqual(data.type, 'artist') || _.isEqual(data.type, 'album')) { childrenData = await this.plex.getLibraryData(data.key.split('/')[3]); } let dataDetails: Record = {}; @@ -1460,268 +1462,319 @@ class PlexMeetsHomeAssistant extends HTMLElement { this.seasonsElem.style.top = `${top + 2000}px`; } - _.forEach(childrenData, childData => { - if (this.seasonsElem && this.plex) { - this.seasonsElemHidden = false; - const seasonContainer = document.createElement('div'); - seasonContainer.className = 'seasonContainer'; - 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=${childData.thumb}&X-Plex-Token=${this.config.token}`; - - const seasonElem = document.createElement('div'); - seasonElem.className = 'seasonElem'; - seasonElem.style.width = `${CSS_STYLE.width}px`; - if (_.isEqual(childData.type, 'album')) { - seasonElem.style.height = `${CSS_STYLE.width}px`; - } else { - seasonElem.style.height = `${CSS_STYLE.height - 3}px`; + if (_.isEqual(_.get(childrenData[0], 'type'), 'track')) { + if (this.episodesElem) { + this.episodesElemHidden = false; + this.episodesElem.style.display = 'block'; + this.episodesElem.innerHTML = ''; + this.episodesElem.style.transition = `0s`; + 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(data.type, 'album')) { + this.episodesElem.append(tableView); } + let isEven = false; + _.forEach(childrenData, childData => { + if (this.episodesElem && this.playController && this.plex) { + if (_.isEqual(childData.type, 'track')) { + tableView.append( + createTrackView(this.playController, this.plex, childData, this.fontSize1, this.fontSize2, isEven) + ); + isEven = !isEven; + } else { + this.episodesElem.append( + createEpisodesView(this.playController, this.plex, childData, this.fontSize1, this.fontSize2) + ); + } + } + }); + clearInterval(this.episodesLoadTimeout); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; + if (this.activeMovieElem) { + this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; + } else { + this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; + } - seasonElem.style.backgroundImage = `url('${thumbURL}')`; - seasonElem.dataset.clicked = 'false'; + this.resizeBackground(); + } + }, 200); + clearInterval(this.episodesElemFreshlyLoadedTimeout); + this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { + this.episodesElemFreshlyLoaded = false; + }, 700); + } + } else { + _.forEach(childrenData, childData => { + if (this.seasonsElem && this.plex) { + console.log(childData); + this.seasonsElemHidden = false; + const seasonContainer = document.createElement('div'); + seasonContainer.className = 'seasonContainer'; + 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=${childData.thumb}&X-Plex-Token=${this.config.token}`; + + const seasonElem = document.createElement('div'); + seasonElem.className = 'seasonElem'; + seasonElem.style.width = `${CSS_STYLE.width}px`; + if (_.isEqual(childData.type, 'album')) { + seasonElem.style.height = `${CSS_STYLE.width}px`; + } else { + seasonElem.style.height = `${CSS_STYLE.height - 3}px`; + } - if (this.playController && !this.playController.isPlaySupported(childData)) { - seasonElem.style.cursor = 'pointer'; - } + seasonElem.style.backgroundImage = `url('${thumbURL}')`; + seasonElem.dataset.clicked = 'false'; - const interactiveArea = document.createElement('div'); - interactiveArea.className = 'interactiveArea'; - if (childData.leafCount - childData.viewedLeafCount > 0) { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewSeason'; - toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString(); + if (this.playController && !this.playController.isPlaySupported(childData)) { + seasonElem.style.cursor = 'pointer'; + } - toViewElem.style.fontSize = `${this.fontSize4}px`; - toViewElem.style.lineHeight = `${this.fontSize4}px`; - toViewElem.style.padding = `${this.fontSize4 / 2}px`; + const interactiveArea = document.createElement('div'); + interactiveArea.className = 'interactiveArea'; + if (childData.leafCount - childData.viewedLeafCount > 0) { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewSeason'; + toViewElem.innerHTML = (childData.leafCount - childData.viewedLeafCount).toString(); - interactiveArea.appendChild(toViewElem); - } + toViewElem.style.fontSize = `${this.fontSize4}px`; + toViewElem.style.lineHeight = `${this.fontSize4}px`; + toViewElem.style.padding = `${this.fontSize4 / 2}px`; - if (this.playController) { - const playButton = this.playController.getPlayButton(childData.type); - if (this.playController.isPlaySupported(childData)) { - playButton.classList.remove('disabled'); + interactiveArea.appendChild(toViewElem); } - playButton.addEventListener('click', event => { - event.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(childData, true); + + if (this.playController) { + const playButton = this.playController.getPlayButton(childData.type); + if (this.playController.isPlaySupported(childData)) { + playButton.classList.remove('disabled'); } - }); + playButton.addEventListener('click', event => { + event.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(childData, true); + } + }); - interactiveArea.append(playButton); - } + interactiveArea.append(playButton); + } - seasonElem.append(interactiveArea); - seasonContainer.append(seasonElem); - - const seasonTitleElem = document.createElement('div'); - seasonTitleElem.className = 'seasonTitleElem'; - seasonTitleElem.innerHTML = escapeHtml(childData.title); - seasonTitleElem.style.fontSize = `${this.fontSize1}px`; - seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; - seasonContainer.append(seasonTitleElem); - - const seasonEpisodesCount = document.createElement('div'); - seasonEpisodesCount.className = 'seasonEpisodesCount'; - if (childData.leafCount > 0) { - seasonEpisodesCount.innerHTML = `${escapeHtml(childData.leafCount)} episodes`; - } else if (!_.isNil(childData.year)) { - seasonEpisodesCount.innerHTML = `${escapeHtml(childData.year)} `; - } + seasonElem.append(interactiveArea); + seasonContainer.append(seasonElem); + + const seasonTitleElem = document.createElement('div'); + seasonTitleElem.className = 'seasonTitleElem'; + seasonTitleElem.innerHTML = escapeHtml(childData.title); + seasonTitleElem.style.fontSize = `${this.fontSize1}px`; + seasonTitleElem.style.lineHeight = `${this.fontSize1}px`; + seasonContainer.append(seasonTitleElem); + + const seasonEpisodesCount = document.createElement('div'); + seasonEpisodesCount.className = 'seasonEpisodesCount'; + 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.lineHeight = `${this.fontSize2}px`; - seasonContainer.append(seasonEpisodesCount); - - seasonContainer.addEventListener('click', event => { - event.stopPropagation(); - if (this.seasonContainerClickEnabled) { - this.seasonContainerClickEnabled = false; - setTimeout(() => { - this.seasonContainerClickEnabled = true; - }, 500); - if (this.activeMovieElem) { - if (seasonElem.dataset.clicked === 'false') { - if (this.playController) { - this.playController.setPlayActionButtonType(childData.type); - this.playController.setPlayButtonClickFunction((thisEvent: MouseEvent) => { - thisEvent.preventDefault(); - thisEvent.stopPropagation(); - if (this.playController) { - this.playController.play(childData, true); - } - }); - } - if (typeof seasonElem.children[0].children[0] !== 'undefined') { - (seasonElem.children[0].children[0] as HTMLElement).style.display = 'none'; - } + seasonEpisodesCount.style.fontSize = `${this.fontSize2}px`; + seasonEpisodesCount.style.lineHeight = `${this.fontSize2}px`; + seasonContainer.append(seasonEpisodesCount); - seasonElem.dataset.clicked = 'true'; - this.activeMovieElem.style.top = `${top - 1000}px`; - setTimeout(() => { - if (this.activeMovieElem) { - this.activeMovieElem.style.display = 'none'; + seasonContainer.addEventListener('click', event => { + event.stopPropagation(); + if (this.seasonContainerClickEnabled) { + this.seasonContainerClickEnabled = false; + setTimeout(() => { + this.seasonContainerClickEnabled = true; + }, 500); + if (this.activeMovieElem) { + if (seasonElem.dataset.clicked === 'false') { + if (this.playController) { + this.playController.setPlayActionButtonType(childData.type); + this.playController.setPlayButtonClickFunction((thisEvent: MouseEvent) => { + thisEvent.preventDefault(); + thisEvent.stopPropagation(); + if (this.playController) { + this.playController.play(childData, true); + } + }); + } + if (typeof seasonElem.children[0].children[0] !== 'undefined') { + (seasonElem.children[0].children[0] as HTMLElement).style.display = 'none'; } - }, 500); - this.scrollDownInactiveSeasons(); + seasonElem.dataset.clicked = 'true'; + this.activeMovieElem.style.top = `${top - 1000}px`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.display = 'none'; + } + }, 500); - if (this.activeMovieElem) { - seasonContainer.style.top = `${-getHeight(this.activeMovieElem)}px`; - } else { - seasonContainer.style.top = `${-this.minExpandedHeight}px`; - } + this.scrollDownInactiveSeasons(); - seasonElem.dataset.type = childData.type; - seasonElem.style.width = `${this.minExpandedWidth}px`; - if (_.isEqual(childData.type, 'album')) { - seasonElem.style.height = `${this.minExpandedWidth}px`; - } else { - seasonElem.style.height = `${this.minExpandedHeight - 6}px`; - } - seasonElem.style.zIndex = '3'; + if (this.activeMovieElem) { + seasonContainer.style.top = `${-getHeight(this.activeMovieElem)}px`; + } else { + seasonContainer.style.top = `${-this.minExpandedHeight}px`; + } - seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - - getOffset(this.activeMovieElem).left}px`; + seasonElem.dataset.type = childData.type; + seasonElem.style.width = `${this.minExpandedWidth}px`; + if (_.isEqual(childData.type, 'album')) { + seasonElem.style.height = `${this.minExpandedWidth}px`; + } else { + seasonElem.style.height = `${this.minExpandedHeight - 6}px`; + } + seasonElem.style.zIndex = '3'; - seasonTitleElem.style.color = 'rgba(255,255,255,0)'; - seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; + seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - + getOffset(this.activeMovieElem).left}px`; - if (this.detailElem) { - (this.detailElem.children[1] as HTMLElement).innerHTML = childData.title; - } - (async (): Promise => { - if (this.plex && (childData.leafCount > 0 || _.isEqual(childData.type, 'album'))) { - this.episodesElemFreshlyLoaded = true; - const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]); - if (this.episodesElem) { - this.episodesElemHidden = false; - this.episodesElem.style.display = 'block'; - this.episodesElem.innerHTML = ''; - this.episodesElem.style.transition = `0s`; - 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 => { - if (this.episodesElem && this.playController && this.plex) { - if (_.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); - this.episodesLoadTimeout = setTimeout(() => { - if (this.episodesElem) { - this.episodesElem.style.transition = `0.7s`; - if (this.activeMovieElem) { - this.episodesElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; - } else { - this.episodesElem.style.top = `${top + this.minExpandedHeight + 16}px`; - } + seasonTitleElem.style.color = 'rgba(255,255,255,0)'; + seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; - this.resizeBackground(); + if (this.detailElem) { + (this.detailElem.children[1] as HTMLElement).innerHTML = childData.title; + } + (async (): Promise => { + if (this.plex && (childData.leafCount > 0 || _.isEqual(childData.type, 'album'))) { + this.episodesElemFreshlyLoaded = true; + const episodesData = await this.plex.getLibraryData(childData.key.split('/')[3]); + if (this.episodesElem) { + this.episodesElemHidden = false; + this.episodesElem.style.display = 'block'; + this.episodesElem.innerHTML = ''; + this.episodesElem.style.transition = `0s`; + 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); } - }, 200); - clearInterval(this.episodesElemFreshlyLoadedTimeout); - this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { - this.episodesElemFreshlyLoaded = false; - }, 700); + let isEven = false; + _.forEach(episodesData, episodeData => { + if (this.episodesElem && this.playController && this.plex) { + if (_.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); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; + 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(); + } + }, 200); + clearInterval(this.episodesElemFreshlyLoadedTimeout); + this.episodesElemFreshlyLoadedTimeout = setTimeout(() => { + this.episodesElemFreshlyLoaded = false; + }, 700); + } } + })(); + } else { + // todo: change title from season and change media type of play button back + if (this.playController) { + this.playController.setPlayActionButtonType(childData.type); } - })(); - } else { - // todo: change title from season and change media type of play button back - if (this.playController) { - this.playController.setPlayActionButtonType(childData.type); - } - seasonContainer.style.top = `${seasonContainer.dataset.top}px`; - this.minimizeSeasons(); - this.hideEpisodes(); - this.activeMovieElem.style.display = `block`; - setTimeout(() => { - if (this.activeMovieElem) { - this.activeMovieElem.style.top = `${top + 16}px`; - } - }, 10); + seasonContainer.style.top = `${seasonContainer.dataset.top}px`; + this.minimizeSeasons(); + this.hideEpisodes(); + this.activeMovieElem.style.display = `block`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.top = `${top + 16}px`; + } + }, 10); - if (this.detailElem && (this.detailElem.children[1] as HTMLElement)) { - const { year } = (this.detailElem.children[1] as HTMLElement).dataset; - if (year) { - (this.detailElem.children[1] as HTMLElement).innerHTML = year; + if (this.detailElem && (this.detailElem.children[1] as HTMLElement)) { + const { year } = (this.detailElem.children[1] as HTMLElement).dataset; + if (year) { + (this.detailElem.children[1] as HTMLElement).innerHTML = year; + } } } } } - } - }); + }); - this.seasonsElem.append(seasonContainer); - } - }); + this.seasonsElem.append(seasonContainer); + } + }); - _.forEach((this.seasonsElem as HTMLElement).children, elem => { - const seasonElem = elem as HTMLElement; - const left = seasonElem.offsetLeft; - const topElem = seasonElem.offsetTop; - seasonElem.style.left = `${left}px`; - seasonElem.dataset.left = `${left}`; - seasonElem.style.top = `${topElem}px`; - seasonElem.dataset.top = `${topElem}`; - }); - _.forEach((this.seasonsElem as HTMLElement).children, elem => { - const seasonElem = elem as HTMLElement; - seasonElem.style.position = 'absolute'; - }); + _.forEach((this.seasonsElem as HTMLElement).children, elem => { + const seasonElem = elem as HTMLElement; + const left = seasonElem.offsetLeft; + const topElem = seasonElem.offsetTop; + seasonElem.style.left = `${left}px`; + seasonElem.dataset.left = `${left}`; + seasonElem.style.top = `${topElem}px`; + seasonElem.dataset.top = `${topElem}`; + }); + _.forEach((this.seasonsElem as HTMLElement).children, elem => { + const seasonElem = elem as HTMLElement; + seasonElem.style.position = 'absolute'; + }); - clearInterval(this.seasonElemFreshlyLoadedTimeout); - this.seasonElemFreshlyLoadedTimeout = setTimeout(() => { - this.seasonElemFreshlyLoaded = false; - }, 700); - - clearInterval(this.showSeasonElemTimeout); - this.showSeasonElemTimeout = setTimeout(() => { - if (this.seasonsElem) { - this.seasonsElem.style.transition = `0.7s`; - if (this.activeMovieElem) { - this.seasonsElem.style.top = `${top + getHeight(this.activeMovieElem) + 16 * 2}px`; - } else { - this.seasonsElem.style.top = `${top + this.minExpandedHeight + 16}px`; - } + clearInterval(this.seasonElemFreshlyLoadedTimeout); + this.seasonElemFreshlyLoadedTimeout = setTimeout(() => { + this.seasonElemFreshlyLoaded = false; + }, 700); - this.resizeBackground(); - } - }, 200); + clearInterval(this.showSeasonElemTimeout); + this.showSeasonElemTimeout = setTimeout(() => { + if (this.seasonsElem) { + this.seasonsElem.style.transition = `0.7s`; + 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(); + } + }, 200); + } } else { this.episodesElemFreshlyLoaded = true; if (this.episodesElem) { @@ -1893,8 +1946,8 @@ class PlexMeetsHomeAssistant extends HTMLElement { movieElem.style.width = `${CSS_STYLE.width}px`; movieElem.style.height = `${CSS_STYLE.height}px`; - if (!_.isNil(data.channelCallSign) || _.isEqual(data.type, 'artist')) { - if (!_.isEqual(data.type, 'artist')) { + if (!_.isNil(data.channelCallSign) || _.isEqual(data.type, 'artist') || _.isEqual(data.type, 'album')) { + if (!_.isEqual(data.type, 'artist') && !_.isEqual(data.type, 'album')) { movieElem.style.backgroundSize = '80%'; } movieElem.style.backgroundColor = 'rgba(0,0,0,0.2)'; @@ -2060,6 +2113,9 @@ class PlexMeetsHomeAssistant extends HTMLElement { if (config.protocol) { this.plexProtocol = config.protocol; } + if (config.displayType && !_.isEmpty(config.displayType)) { + this.displayType = config.displayType; + } if (config.useHorizontalScroll && _.isEqual(config.useHorizontalScroll, 'Yes')) { this.useHorizontalScroll = true; }