From e44f141c64e14d6bcda63f238770c7777b125544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20Nyi=CC=81ri?= Date: Sat, 5 Jun 2021 21:29:42 +0200 Subject: [PATCH] Add: API endpoint for movie details --- dist/plex-meets-homeassistant.js | 397 +++++++++++++++-------------- src/modules/Plex.ts | 9 + src/plex-meets-homeassistant.ts | 418 ++++++++++++++++--------------- 3 files changed, 424 insertions(+), 400 deletions(-) diff --git a/dist/plex-meets-homeassistant.js b/dist/plex-meets-homeassistant.js index f47d255..2a2d4dc 100644 --- a/dist/plex-meets-homeassistant.js +++ b/dist/plex-meets-homeassistant.js @@ -18724,6 +18724,12 @@ class Plex { }); return this.exportSectionsData(await Promise.all(sectionsRequests)); }; + this.getDetails = async (id) => { + const url = `${this.protocol}://${this.ip}:${this.port}/library/metadata/${id}?includeConcerts=1&includeExtras=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeReviews=1&includeChapters=1&includeStations=1&includeExternalMedia=1&asyncAugmentMetadata=1&asyncCheckFiles=1&asyncRefreshAnalysis=1&asyncRefreshLocalMediaAgent=1&X-Plex-Token=${this.token}`; + return (await axios.get(url, { + timeout: this.requestTimeout + })).data.MediaContainer.Metadata[0]; + }; this.getLibraryData = async (id) => { const url = `${this.protocol}://${this.ip}:${this.port}/library/metadata/${id}/children?X-Plex-Token=${this.token}`; return (await axios.get(url, { @@ -20032,210 +20038,215 @@ class PlexMeetsHomeAssistant extends HTMLElement { } }, 200); } - if (this.plex && data.childCount > 0) { - this.seasonElemFreshlyLoaded = true; - const seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); - if (this.seasonsElem) { - this.seasonsElem.style.display = 'block'; - this.seasonsElem.innerHTML = ''; - this.seasonsElem.style.transition = `0s`; - this.seasonsElem.style.top = `${top + 2000}px`; - } - lodash.forEach(seasonsData, seasonData => { + if (this.plex) { + if (data.childCount > 0) { + this.seasonElemFreshlyLoaded = true; + const seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); if (this.seasonsElem) { - this.seasonsElemHidden = false; - const seasonContainer = document.createElement('div'); - seasonContainer.className = 'seasonContainer'; - seasonContainer.style.width = `${CSS_STYLE.width}px`; - const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.expandedWidth}&height=${CSS_STYLE.expandedHeight}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; - const seasonElem = document.createElement('div'); - seasonElem.className = 'seasonElem'; - seasonElem.style.width = `${CSS_STYLE.width}px`; - seasonElem.style.height = `${CSS_STYLE.height - 3}px`; - seasonElem.style.backgroundImage = `url('${thumbURL}')`; - seasonElem.dataset.clicked = 'false'; - if (this.playController && !this.playController.isPlaySupported(seasonData)) { - seasonElem.style.cursor = 'pointer'; - } - const interactiveArea = document.createElement('div'); - interactiveArea.className = 'interactiveArea'; - if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewSeason'; - toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); - interactiveArea.appendChild(toViewElem); - } - if (this.playController && this.playController.isPlaySupported(seasonData)) { - const playButton = this.getPlayButton(); - playButton.addEventListener('click', event => { + this.seasonsElem.style.display = 'block'; + this.seasonsElem.innerHTML = ''; + this.seasonsElem.style.transition = `0s`; + this.seasonsElem.style.top = `${top + 2000}px`; + } + lodash.forEach(seasonsData, seasonData => { + if (this.seasonsElem) { + this.seasonsElemHidden = false; + const seasonContainer = document.createElement('div'); + seasonContainer.className = 'seasonContainer'; + seasonContainer.style.width = `${CSS_STYLE.width}px`; + const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.expandedWidth}&height=${CSS_STYLE.expandedHeight}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; + const seasonElem = document.createElement('div'); + seasonElem.className = 'seasonElem'; + seasonElem.style.width = `${CSS_STYLE.width}px`; + seasonElem.style.height = `${CSS_STYLE.height - 3}px`; + seasonElem.style.backgroundImage = `url('${thumbURL}')`; + seasonElem.dataset.clicked = 'false'; + if (this.playController && !this.playController.isPlaySupported(seasonData)) { + seasonElem.style.cursor = 'pointer'; + } + const interactiveArea = document.createElement('div'); + interactiveArea.className = 'interactiveArea'; + if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewSeason'; + toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); + interactiveArea.appendChild(toViewElem); + } + if (this.playController && this.playController.isPlaySupported(seasonData)) { + const playButton = this.getPlayButton(); + playButton.addEventListener('click', event => { + event.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(seasonData, true); + } + }); + interactiveArea.append(playButton); + } + seasonElem.append(interactiveArea); + seasonContainer.append(seasonElem); + const seasonTitleElem = document.createElement('div'); + seasonTitleElem.className = 'seasonTitleElem'; + seasonTitleElem.innerHTML = escapeHtml(seasonData.title); + seasonContainer.append(seasonTitleElem); + const seasonEpisodesCount = document.createElement('div'); + seasonEpisodesCount.className = 'seasonEpisodesCount'; + seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; + seasonContainer.append(seasonEpisodesCount); + seasonContainer.addEventListener('click', event => { event.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(seasonData, true); - } - }); - interactiveArea.append(playButton); - } - seasonElem.append(interactiveArea); - seasonContainer.append(seasonElem); - const seasonTitleElem = document.createElement('div'); - seasonTitleElem.className = 'seasonTitleElem'; - seasonTitleElem.innerHTML = escapeHtml(seasonData.title); - seasonContainer.append(seasonTitleElem); - const seasonEpisodesCount = document.createElement('div'); - seasonEpisodesCount.className = 'seasonEpisodesCount'; - seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; - 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 (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 (this.seasonContainerClickEnabled) { + this.seasonContainerClickEnabled = false; + setTimeout(() => { + this.seasonContainerClickEnabled = true; + }, 500); + if (this.activeMovieElem) { + if (seasonElem.dataset.clicked === 'false') { + if (typeof seasonElem.children[0].children[0] !== 'undefined') { + seasonElem.children[0].children[0].style.display = 'none'; } - }, 500); - this.scrollDownInactiveSeasons(); - seasonContainer.style.top = `${-CSS_STYLE.expandedHeight}px`; - seasonElem.style.width = `${CSS_STYLE.expandedWidth}px`; - seasonElem.style.height = `${CSS_STYLE.expandedHeight - 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 = seasonData.title; - } - (async () => { - if (seasonData.leafCount > 0 && this.plex) { - this.episodesElemFreshlyLoaded = true; - const episodesData = await this.plex.getLibraryData(seasonData.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`; - lodash.forEach(episodesData, episodeData => { - if (this.episodesElem) { - const episodeContainer = document.createElement('div'); - episodeContainer.className = 'episodeContainer'; - episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`; - const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`; - const episodeElem = document.createElement('div'); - episodeElem.className = 'episodeElem'; - episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`; - episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`; - episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`; - episodeElem.dataset.clicked = 'false'; - if (typeof episodeData.lastViewedAt === 'undefined') { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewEpisode'; - episodeElem.appendChild(toViewElem); - } - if (this.playController && this.playController.isPlaySupported(episodeData)) { - const episodeInteractiveArea = document.createElement('div'); - episodeInteractiveArea.className = 'interactiveArea'; - const episodePlayButton = document.createElement('button'); - episodePlayButton.name = 'playButton'; - episodePlayButton.addEventListener('click', episodeEvent => { + seasonElem.dataset.clicked = 'true'; + this.activeMovieElem.style.top = `${top - 1000}px`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.display = 'none'; + } + }, 500); + this.scrollDownInactiveSeasons(); + seasonContainer.style.top = `${-CSS_STYLE.expandedHeight}px`; + seasonElem.style.width = `${CSS_STYLE.expandedWidth}px`; + seasonElem.style.height = `${CSS_STYLE.expandedHeight - 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 = seasonData.title; + } + (async () => { + if (seasonData.leafCount > 0 && this.plex) { + this.episodesElemFreshlyLoaded = true; + const episodesData = await this.plex.getLibraryData(seasonData.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`; + lodash.forEach(episodesData, episodeData => { + if (this.episodesElem) { + const episodeContainer = document.createElement('div'); + episodeContainer.className = 'episodeContainer'; + episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`; + const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`; + const episodeElem = document.createElement('div'); + episodeElem.className = 'episodeElem'; + episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`; + episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`; + episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`; + episodeElem.dataset.clicked = 'false'; + if (typeof episodeData.lastViewedAt === 'undefined') { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewEpisode'; + episodeElem.appendChild(toViewElem); + } + if (this.playController && this.playController.isPlaySupported(episodeData)) { + const episodeInteractiveArea = document.createElement('div'); + episodeInteractiveArea.className = 'interactiveArea'; + const episodePlayButton = document.createElement('button'); + episodePlayButton.name = 'playButton'; + episodePlayButton.addEventListener('click', episodeEvent => { + episodeEvent.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(episodeData, true); + } + }); + episodeInteractiveArea.append(episodePlayButton); + episodeElem.append(episodeInteractiveArea); + } + episodeContainer.append(episodeElem); + const episodeTitleElem = document.createElement('div'); + episodeTitleElem.className = 'episodeTitleElem'; + episodeTitleElem.innerHTML = escapeHtml(episodeData.title); + episodeContainer.append(episodeTitleElem); + const episodeNumber = document.createElement('div'); + episodeNumber.className = 'episodeNumber'; + episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`); + episodeContainer.append(episodeNumber); + episodeContainer.addEventListener('click', episodeEvent => { episodeEvent.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(episodeData, true); - } }); - episodeInteractiveArea.append(episodePlayButton); - episodeElem.append(episodeInteractiveArea); + this.episodesElem.append(episodeContainer); + } + }); + clearInterval(this.episodesLoadTimeout); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; + this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; + this.resizeBackground(); } - episodeContainer.append(episodeElem); - const episodeTitleElem = document.createElement('div'); - episodeTitleElem.className = 'episodeTitleElem'; - episodeTitleElem.innerHTML = escapeHtml(episodeData.title); - episodeContainer.append(episodeTitleElem); - const episodeNumber = document.createElement('div'); - episodeNumber.className = 'episodeNumber'; - episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`); - episodeContainer.append(episodeNumber); - episodeContainer.addEventListener('click', episodeEvent => { - episodeEvent.stopPropagation(); - }); - this.episodesElem.append(episodeContainer); - } - }); - clearInterval(this.episodesLoadTimeout); - this.episodesLoadTimeout = setTimeout(() => { - if (this.episodesElem) { - this.episodesElem.style.transition = `0.7s`; - this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; - 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 { + 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; } - } - })(); - } - else { - 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`; - this.seasonsElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; - this.resizeBackground(); - } - }, 200); + }); + 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`; + this.seasonsElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; + this.resizeBackground(); + } + }, 200); + } + else { + console.log(await this.plex.getDetails(data.key.split('/')[3])); + } } }; this.resizeBackground = () => { diff --git a/src/modules/Plex.ts b/src/modules/Plex.ts index 57abdde..304295e 100644 --- a/src/modules/Plex.ts +++ b/src/modules/Plex.ts @@ -90,6 +90,15 @@ class Plex { return this.exportSectionsData(await Promise.all(sectionsRequests)); }; + getDetails = async (id: number): Promise => { + const url = `${this.protocol}://${this.ip}:${this.port}/library/metadata/${id}?includeConcerts=1&includeExtras=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeReviews=1&includeChapters=1&includeStations=1&includeExternalMedia=1&asyncAugmentMetadata=1&asyncCheckFiles=1&asyncRefreshAnalysis=1&asyncRefreshLocalMediaAgent=1&X-Plex-Token=${this.token}`; + return ( + await axios.get(url, { + timeout: this.requestTimeout + }) + ).data.MediaContainer.Metadata[0]; + }; + getLibraryData = async (id: number): Promise => { const url = `${this.protocol}://${this.ip}:${this.port}/library/metadata/${id}/children?X-Plex-Token=${this.token}`; return ( diff --git a/src/plex-meets-homeassistant.ts b/src/plex-meets-homeassistant.ts index 6cb5942..9915e04 100644 --- a/src/plex-meets-homeassistant.ts +++ b/src/plex-meets-homeassistant.ts @@ -526,240 +526,244 @@ class PlexMeetsHomeAssistant extends HTMLElement { } }, 200); } - if (this.plex && data.childCount > 0) { - this.seasonElemFreshlyLoaded = true; - const seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); - if (this.seasonsElem) { - this.seasonsElem.style.display = 'block'; - this.seasonsElem.innerHTML = ''; - this.seasonsElem.style.transition = `0s`; - this.seasonsElem.style.top = `${top + 2000}px`; - } - - _.forEach(seasonsData, seasonData => { + if (this.plex) { + if (data.childCount > 0) { + this.seasonElemFreshlyLoaded = true; + const seasonsData = await this.plex.getLibraryData(data.key.split('/')[3]); if (this.seasonsElem) { - this.seasonsElemHidden = false; - const seasonContainer = document.createElement('div'); - seasonContainer.className = 'seasonContainer'; - seasonContainer.style.width = `${CSS_STYLE.width}px`; - const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.expandedWidth}&height=${CSS_STYLE.expandedHeight}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; - - const seasonElem = document.createElement('div'); - seasonElem.className = 'seasonElem'; - seasonElem.style.width = `${CSS_STYLE.width}px`; - seasonElem.style.height = `${CSS_STYLE.height - 3}px`; - seasonElem.style.backgroundImage = `url('${thumbURL}')`; - seasonElem.dataset.clicked = 'false'; - - if (this.playController && !this.playController.isPlaySupported(seasonData)) { - seasonElem.style.cursor = 'pointer'; - } + this.seasonsElem.style.display = 'block'; + this.seasonsElem.innerHTML = ''; + this.seasonsElem.style.transition = `0s`; + this.seasonsElem.style.top = `${top + 2000}px`; + } - const interactiveArea = document.createElement('div'); - interactiveArea.className = 'interactiveArea'; - if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewSeason'; - toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); - interactiveArea.appendChild(toViewElem); - } + _.forEach(seasonsData, seasonData => { + if (this.seasonsElem) { + this.seasonsElemHidden = false; + const seasonContainer = document.createElement('div'); + seasonContainer.className = 'seasonContainer'; + seasonContainer.style.width = `${CSS_STYLE.width}px`; + const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.expandedWidth}&height=${CSS_STYLE.expandedHeight}&minSize=1&upscale=1&url=${seasonData.thumb}&X-Plex-Token=${this.config.token}`; + + const seasonElem = document.createElement('div'); + seasonElem.className = 'seasonElem'; + seasonElem.style.width = `${CSS_STYLE.width}px`; + seasonElem.style.height = `${CSS_STYLE.height - 3}px`; + seasonElem.style.backgroundImage = `url('${thumbURL}')`; + seasonElem.dataset.clicked = 'false'; + + if (this.playController && !this.playController.isPlaySupported(seasonData)) { + seasonElem.style.cursor = 'pointer'; + } - if (this.playController && this.playController.isPlaySupported(seasonData)) { - const playButton = this.getPlayButton(); - playButton.addEventListener('click', event => { - event.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(seasonData, true); - } - }); + const interactiveArea = document.createElement('div'); + interactiveArea.className = 'interactiveArea'; + if (seasonData.leafCount - seasonData.viewedLeafCount > 0) { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewSeason'; + toViewElem.innerHTML = (seasonData.leafCount - seasonData.viewedLeafCount).toString(); + interactiveArea.appendChild(toViewElem); + } - interactiveArea.append(playButton); - } - seasonElem.append(interactiveArea); - seasonContainer.append(seasonElem); - - const seasonTitleElem = document.createElement('div'); - seasonTitleElem.className = 'seasonTitleElem'; - seasonTitleElem.innerHTML = escapeHtml(seasonData.title); - seasonContainer.append(seasonTitleElem); - - const seasonEpisodesCount = document.createElement('div'); - seasonEpisodesCount.className = 'seasonEpisodesCount'; - seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; - 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 (typeof seasonElem.children[0].children[0] !== 'undefined') { - (seasonElem.children[0].children[0] as HTMLElement).style.display = 'none'; - } + if (this.playController && this.playController.isPlaySupported(seasonData)) { + const playButton = this.getPlayButton(); + playButton.addEventListener('click', event => { + event.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(seasonData, true); + } + }); - seasonElem.dataset.clicked = 'true'; - this.activeMovieElem.style.top = `${top - 1000}px`; - setTimeout(() => { - if (this.activeMovieElem) { - this.activeMovieElem.style.display = 'none'; - } - }, 500); + interactiveArea.append(playButton); + } + seasonElem.append(interactiveArea); + seasonContainer.append(seasonElem); + + const seasonTitleElem = document.createElement('div'); + seasonTitleElem.className = 'seasonTitleElem'; + seasonTitleElem.innerHTML = escapeHtml(seasonData.title); + seasonContainer.append(seasonTitleElem); - this.scrollDownInactiveSeasons(); + const seasonEpisodesCount = document.createElement('div'); + seasonEpisodesCount.className = 'seasonEpisodesCount'; + seasonEpisodesCount.innerHTML = `${escapeHtml(seasonData.leafCount)} episodes`; + seasonContainer.append(seasonEpisodesCount); - seasonContainer.style.top = `${-CSS_STYLE.expandedHeight}px`; - seasonElem.style.width = `${CSS_STYLE.expandedWidth}px`; - seasonElem.style.height = `${CSS_STYLE.expandedHeight - 6}px`; - seasonElem.style.zIndex = '3'; + 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 (typeof seasonElem.children[0].children[0] !== 'undefined') { + (seasonElem.children[0].children[0] as HTMLElement).style.display = 'none'; + } + + seasonElem.dataset.clicked = 'true'; + this.activeMovieElem.style.top = `${top - 1000}px`; + setTimeout(() => { + if (this.activeMovieElem) { + this.activeMovieElem.style.display = 'none'; + } + }, 500); - seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - - getOffset(this.activeMovieElem).left}px`; + this.scrollDownInactiveSeasons(); - seasonTitleElem.style.color = 'rgba(255,255,255,0)'; - seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; + seasonContainer.style.top = `${-CSS_STYLE.expandedHeight}px`; + seasonElem.style.width = `${CSS_STYLE.expandedWidth}px`; + seasonElem.style.height = `${CSS_STYLE.expandedHeight - 6}px`; + seasonElem.style.zIndex = '3'; - if (this.detailElem) { - (this.detailElem.children[1] as HTMLElement).innerHTML = seasonData.title; - } - (async (): Promise => { - if (seasonData.leafCount > 0 && this.plex) { - this.episodesElemFreshlyLoaded = true; - const episodesData = await this.plex.getLibraryData(seasonData.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`; - _.forEach(episodesData, episodeData => { - if (this.episodesElem) { - const episodeContainer = document.createElement('div'); - episodeContainer.className = 'episodeContainer'; - episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`; - const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`; - - const episodeElem = document.createElement('div'); - episodeElem.className = 'episodeElem'; - episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`; - episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`; - episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`; - episodeElem.dataset.clicked = 'false'; - - if (typeof episodeData.lastViewedAt === 'undefined') { - const toViewElem = document.createElement('div'); - toViewElem.className = 'toViewEpisode'; - episodeElem.appendChild(toViewElem); - } + seasonElem.style.marginLeft = `-${getOffset(seasonElem).left - + getOffset(this.activeMovieElem).left}px`; - if (this.playController && this.playController.isPlaySupported(episodeData)) { - const episodeInteractiveArea = document.createElement('div'); - episodeInteractiveArea.className = 'interactiveArea'; + seasonTitleElem.style.color = 'rgba(255,255,255,0)'; + seasonEpisodesCount.style.color = 'rgba(255,255,255,0)'; - const episodePlayButton = document.createElement('button'); - episodePlayButton.name = 'playButton'; - episodePlayButton.addEventListener('click', episodeEvent => { + if (this.detailElem) { + (this.detailElem.children[1] as HTMLElement).innerHTML = seasonData.title; + } + (async (): Promise => { + if (seasonData.leafCount > 0 && this.plex) { + this.episodesElemFreshlyLoaded = true; + const episodesData = await this.plex.getLibraryData(seasonData.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`; + _.forEach(episodesData, episodeData => { + if (this.episodesElem) { + const episodeContainer = document.createElement('div'); + episodeContainer.className = 'episodeContainer'; + episodeContainer.style.width = `${CSS_STYLE.episodeWidth}px`; + const episodeThumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${CSS_STYLE.episodeWidth}&height=${CSS_STYLE.episodeHeight}&minSize=1&upscale=1&url=${episodeData.thumb}&X-Plex-Token=${this.config.token}`; + + const episodeElem = document.createElement('div'); + episodeElem.className = 'episodeElem'; + episodeElem.style.width = `${CSS_STYLE.episodeWidth}px`; + episodeElem.style.height = `${CSS_STYLE.episodeHeight}px`; + episodeElem.style.backgroundImage = `url('${episodeThumbURL}')`; + episodeElem.dataset.clicked = 'false'; + + if (typeof episodeData.lastViewedAt === 'undefined') { + const toViewElem = document.createElement('div'); + toViewElem.className = 'toViewEpisode'; + episodeElem.appendChild(toViewElem); + } + + if (this.playController && this.playController.isPlaySupported(episodeData)) { + const episodeInteractiveArea = document.createElement('div'); + episodeInteractiveArea.className = 'interactiveArea'; + + const episodePlayButton = document.createElement('button'); + episodePlayButton.name = 'playButton'; + episodePlayButton.addEventListener('click', episodeEvent => { + episodeEvent.stopPropagation(); + if (this.plex && this.playController) { + this.playController.play(episodeData, true); + } + }); + + episodeInteractiveArea.append(episodePlayButton); + episodeElem.append(episodeInteractiveArea); + } + episodeContainer.append(episodeElem); + + const episodeTitleElem = document.createElement('div'); + episodeTitleElem.className = 'episodeTitleElem'; + episodeTitleElem.innerHTML = escapeHtml(episodeData.title); + episodeContainer.append(episodeTitleElem); + + const episodeNumber = document.createElement('div'); + episodeNumber.className = 'episodeNumber'; + episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`); + episodeContainer.append(episodeNumber); + + episodeContainer.addEventListener('click', episodeEvent => { episodeEvent.stopPropagation(); - if (this.plex && this.playController) { - this.playController.play(episodeData, true); - } }); - episodeInteractiveArea.append(episodePlayButton); - episodeElem.append(episodeInteractiveArea); + this.episodesElem.append(episodeContainer); + } + }); + clearInterval(this.episodesLoadTimeout); + this.episodesLoadTimeout = setTimeout(() => { + if (this.episodesElem) { + this.episodesElem.style.transition = `0.7s`; + this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; + + this.resizeBackground(); } - episodeContainer.append(episodeElem); - - const episodeTitleElem = document.createElement('div'); - episodeTitleElem.className = 'episodeTitleElem'; - episodeTitleElem.innerHTML = escapeHtml(episodeData.title); - episodeContainer.append(episodeTitleElem); - - const episodeNumber = document.createElement('div'); - episodeNumber.className = 'episodeNumber'; - episodeNumber.innerHTML = escapeHtml(`Episode ${escapeHtml(episodeData.index)}`); - episodeContainer.append(episodeNumber); - - episodeContainer.addEventListener('click', episodeEvent => { - episodeEvent.stopPropagation(); - }); - - this.episodesElem.append(episodeContainer); - } - }); - clearInterval(this.episodesLoadTimeout); - this.episodesLoadTimeout = setTimeout(() => { - if (this.episodesElem) { - this.episodesElem.style.transition = `0.7s`; - this.episodesElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; - - 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 { - 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); + })(); + } else { + 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.seasonElemFreshlyLoadedTimeout); + this.seasonElemFreshlyLoadedTimeout = setTimeout(() => { + this.seasonElemFreshlyLoaded = false; + }, 700); - clearInterval(this.showSeasonElemTimeout); - this.showSeasonElemTimeout = setTimeout(() => { - if (this.seasonsElem) { - this.seasonsElem.style.transition = `0.7s`; - this.seasonsElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; + clearInterval(this.showSeasonElemTimeout); + this.showSeasonElemTimeout = setTimeout(() => { + if (this.seasonsElem) { + this.seasonsElem.style.transition = `0.7s`; + this.seasonsElem.style.top = `${top + CSS_STYLE.expandedHeight + 16}px`; - this.resizeBackground(); - } - }, 200); + this.resizeBackground(); + } + }, 200); + } else { + console.log(await this.plex.getDetails(data.key.split('/')[3])); + } } };