From 9ad716a42aa28f998d553f5b8d2fce78343d548c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20Nyi=CC=81ri?= Date: Sat, 12 Jun 2021 20:39:47 +0200 Subject: [PATCH] Add: Bottom and top boundaries for scrolling - includes bug for full height --- dist/plex-meets-homeassistant.js | 42 ++++++++++++++++++++++---------- src/modules/utils.ts | 19 ++++++++++++++- src/plex-meets-homeassistant.ts | 34 ++++++++++++++------------ 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/dist/plex-meets-homeassistant.js b/dist/plex-meets-homeassistant.js index 8370a80..c3bb67a 100644 --- a/dist/plex-meets-homeassistant.js +++ b/dist/plex-meets-homeassistant.js @@ -19157,6 +19157,18 @@ const getOffset = (el) => { } return { top: y, left: x }; }; +const getDetailsBottom = (seasonContainers, episodeContainers) => { + const lastSeasonContainer = seasonContainers[seasonContainers.length - 1]; + const lastEpisodeContainer = episodeContainers[episodeContainers.length - 1]; + let detailBottom = false; + if (seasonContainers.length > 0 && parseInt(lastSeasonContainer.style.top, 10) > 0) { + detailBottom = getHeight(lastSeasonContainer) + parseInt(getOffset(lastSeasonContainer).top, 10) + 10; + } + else if (episodeContainers.length > 0) { + detailBottom = getHeight(lastEpisodeContainer) + parseInt(getOffset(lastEpisodeContainer).top, 10) + 10; + } + return detailBottom; +}; const hasEpisodes = (media) => { let result = false; // eslint-disable-next-line consistent-return @@ -20015,25 +20027,29 @@ class PlexMeetsHomeAssistant extends HTMLElement { }; this.loadInitialData = async () => { window.addEventListener('scroll', () => { + // todo: improve performance by calculating this when needed only if (this.detailsShown && this.activeMovieElem) { - if (this.getTop() + 15 < parseInt(this.activeMovieElem.style.top, 10)) { + const seasonContainers = this.getElementsByClassName('seasonContainer'); + const episodeContainers = this.getElementsByClassName('episodeContainer'); + const seasonElems = this.getElementsByClassName('seasonElem'); + let activeElem = this.activeMovieElem; + // eslint-disable-next-line consistent-return + lodash.forEach(seasonElems, seasonElem => { + if (lodash.isEqual(seasonElem.dataset.clicked, 'true')) { + activeElem = seasonElem; + return false; + } + }); + if (this.getTop() < parseInt(getOffset(activeElem).top, 10) - 70) { window.scroll({ - top: getOffset(this.activeMovieElem).top - 80 + top: getOffset(activeElem).top - 70 }); } else { - // todo move final bottom value to class to safe performance - // todo: make it work with episodes and extras - const season = this.getElementsByClassName('seasons')[0]; - const seasonContainers = this.getElementsByClassName('seasonContainer'); - const lastSeasonContainer = seasonContainers[seasonContainers.length - 1]; - const seasonContainersBottom = parseInt(lastSeasonContainer.style.top, 10) + - parseInt(season.style.top, 10) + - getHeight(lastSeasonContainer) + - 60; - if (this.getTop() + window.innerHeight > seasonContainersBottom) { + const detailBottom = getDetailsBottom(seasonContainers, episodeContainers); + if (detailBottom && this.getTop() + window.innerHeight > detailBottom) { window.scroll({ - top: seasonContainersBottom - window.innerHeight + top: detailBottom - window.innerHeight }); } } diff --git a/src/modules/utils.ts b/src/modules/utils.ts index 5aa9632..40a3b5f 100644 --- a/src/modules/utils.ts +++ b/src/modules/utils.ts @@ -47,6 +47,22 @@ const getOffset = (el: Element): Record => { return { top: y, left: x }; }; +const getDetailsBottom = ( + seasonContainers: HTMLCollectionOf, + episodeContainers: HTMLCollectionOf +): number | false => { + const lastSeasonContainer = seasonContainers[seasonContainers.length - 1]; + const lastEpisodeContainer = episodeContainers[episodeContainers.length - 1]; + let detailBottom: number | false = false; + + if (seasonContainers.length > 0 && parseInt(lastSeasonContainer.style.top, 10) > 0) { + detailBottom = getHeight(lastSeasonContainer) + parseInt(getOffset(lastSeasonContainer).top, 10) + 10; + } else if (episodeContainers.length > 0) { + detailBottom = getHeight(lastEpisodeContainer) + parseInt(getOffset(lastEpisodeContainer).top, 10) + 10; + } + return detailBottom; +}; + const hasEpisodes = (media: Array>): boolean => { let result = false; // eslint-disable-next-line consistent-return @@ -190,5 +206,6 @@ export { isVideoFullScreen, hasEpisodes, getOldPlexServerErrorMessage, - getWidth + getWidth, + getDetailsBottom }; diff --git a/src/plex-meets-homeassistant.ts b/src/plex-meets-homeassistant.ts index 8464d36..f382b66 100644 --- a/src/plex-meets-homeassistant.ts +++ b/src/plex-meets-homeassistant.ts @@ -15,7 +15,7 @@ import { isVideoFullScreen, hasEpisodes, getOldPlexServerErrorMessage, - getWidth + getDetailsBottom } from './modules/utils'; import style from './modules/style'; @@ -149,25 +149,29 @@ class PlexMeetsHomeAssistant extends HTMLElement { loadInitialData = async (): Promise => { window.addEventListener('scroll', () => { + // todo: improve performance by calculating this when needed only if (this.detailsShown && this.activeMovieElem) { - if (this.getTop() + 15 < parseInt(this.activeMovieElem.style.top, 10)) { + const seasonContainers = this.getElementsByClassName('seasonContainer') as HTMLCollectionOf; + const episodeContainers = this.getElementsByClassName('episodeContainer') as HTMLCollectionOf; + const seasonElems = this.getElementsByClassName('seasonElem') as HTMLCollectionOf; + let activeElem = this.activeMovieElem; + // eslint-disable-next-line consistent-return + _.forEach(seasonElems, seasonElem => { + if (_.isEqual(seasonElem.dataset.clicked, 'true')) { + activeElem = seasonElem; + return false; + } + }); + + if (this.getTop() < parseInt(getOffset(activeElem as Element).top, 10) - 70) { window.scroll({ - top: getOffset(this.activeMovieElem as Element).top - 80 + top: getOffset(activeElem as Element).top - 70 }); } else { - // todo move final bottom value to class to safe performance - // todo: make it work with episodes and extras - const season = this.getElementsByClassName('seasons')[0] as HTMLElement; - const seasonContainers = this.getElementsByClassName('seasonContainer'); - const lastSeasonContainer = seasonContainers[seasonContainers.length - 1] as HTMLElement; - const seasonContainersBottom = - parseInt(lastSeasonContainer.style.top, 10) + - parseInt(season.style.top, 10) + - getHeight(lastSeasonContainer) + - 60; - if (this.getTop() + window.innerHeight > seasonContainersBottom) { + const detailBottom = getDetailsBottom(seasonContainers, episodeContainers); + if (detailBottom && this.getTop() + window.innerHeight > detailBottom) { window.scroll({ - top: seasonContainersBottom - window.innerHeight + top: detailBottom - window.innerHeight }); } }