Add: Optimized loading to handle big libraries smoothly without limiting maxCount

pull/16/head
Juraj Nyíri 4 years ago
parent 0828f1c2d5
commit 4bf89dd61d

@ -19606,6 +19606,8 @@ class PlexMeetsHomeAssistant extends HTMLElement {
constructor() { constructor() {
super(...arguments); super(...arguments);
this.plexProtocol = 'http'; this.plexProtocol = 'http';
this.columnsCount = 0;
this.renderedItems = 0;
this.maxRenderCount = false; this.maxRenderCount = false;
this.seasonContainerClickEnabled = true; this.seasonContainerClickEnabled = true;
this.looseSearch = false; this.looseSearch = false;
@ -19625,9 +19627,12 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.contentBGHeight = 0; this.contentBGHeight = 0;
this.loadInitialData = async () => { this.loadInitialData = async () => {
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {
const loadAdditionalRowsCount = 2; // todo: make this configurable
const height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight); const height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
if (window.innerHeight + window.scrollY > height - 300) { if (window.innerHeight + window.scrollY > height - 300) {
console.log('scrolled'); this.maxRenderCount = this.renderedItems - 1 + this.columnsCount * (loadAdditionalRowsCount * 2);
this.renderMovieElems();
this.calculatePositions();
} }
}); });
this.loading = true; this.loading = true;
@ -19702,7 +19707,63 @@ class PlexMeetsHomeAssistant extends HTMLElement {
searchContainer.appendChild(searchInput); searchContainer.appendChild(searchInput);
return searchContainer; return searchContainer;
}; };
this.renderMovieElems = () => {
if (this.data[this.config.libraryName] && this.renderedItems < this.data[this.config.libraryName].length) {
let count = 0;
// eslint-disable-next-line consistent-return
const searchValues = lodash.split(this.searchValue, ' ');
// eslint-disable-next-line consistent-return
let lastRowTop = 0;
const loadAdditionalRowsCount = 2; // todo: make this configurable
// eslint-disable-next-line consistent-return
lodash.forEach(this.data[this.config.libraryName], (movieData) => {
if ((!this.maxCount || this.renderedItems < this.maxCount) &&
(!this.maxRenderCount || this.renderedItems < this.maxRenderCount)) {
const movieElem = this.getMovieElement(movieData);
let shouldRender = false;
if (this.looseSearch) {
let found = false;
// eslint-disable-next-line consistent-return
lodash.forEach(searchValues, value => {
if (!lodash.isEmpty(value) && lodash.includes(lodash.toUpper(movieData.title), lodash.toUpper(value))) {
found = true;
return false;
}
});
if (found || lodash.isEmpty(searchValues[0])) {
shouldRender = true;
}
}
else if (lodash.includes(lodash.toUpper(movieData.title), lodash.toUpper(this.searchValue))) {
shouldRender = true;
}
if (shouldRender) {
count += 1;
if (count > this.renderedItems) {
this.content.appendChild(movieElem);
this.renderedItems += 1;
}
}
if (lastRowTop !== movieElem.getBoundingClientRect().top) {
if (lastRowTop !== 0 && this.columnsCount === 0) {
this.columnsCount = this.renderedItems - 1;
}
lastRowTop = movieElem.getBoundingClientRect().top;
if (!isScrolledIntoView(movieElem) && !this.maxRenderCount) {
this.maxRenderCount = this.renderedItems - 1 + this.columnsCount * loadAdditionalRowsCount;
console.log(`Set max render this.renderedItems to ${this.maxRenderCount}`);
}
}
}
else {
return true;
}
});
}
};
this.renderPage = () => { this.renderPage = () => {
this.renderedItems = 0;
this.columnsCount = 0;
const spinner = document.createElement('div'); const spinner = document.createElement('div');
spinner.style.display = 'flex'; spinner.style.display = 'flex';
spinner.style.alignItems = 'center'; spinner.style.alignItems = 'center';
@ -19732,7 +19793,6 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.content.appendChild(spinner); this.content.appendChild(spinner);
} }
this.card.appendChild(this.content); this.card.appendChild(this.content);
let count = 0;
const contentbg = document.createElement('div'); const contentbg = document.createElement('div');
contentbg.className = 'contentbg'; contentbg.className = 'contentbg';
this.content.appendChild(contentbg); this.content.appendChild(contentbg);
@ -19762,59 +19822,10 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.minimizeAll(); this.minimizeAll();
}); });
}, 1); }, 1);
if (this.data[this.config.libraryName]) {
// eslint-disable-next-line consistent-return
const searchValues = lodash.split(this.searchValue, ' ');
let lastRowTop = 0;
let columnsCount = 0;
const loadAdditionalRowsCount = 2; // todo: make this configurable
// eslint-disable-next-line consistent-return
lodash.forEach(this.data[this.config.libraryName], (movieData) => {
if ((!this.maxCount || count < this.maxCount) && (!this.maxRenderCount || count < this.maxRenderCount)) {
const movieElem = this.getMovieElement(movieData);
let shouldRender = false;
if (this.looseSearch) {
let found = false;
// eslint-disable-next-line consistent-return
lodash.forEach(searchValues, value => {
if (!lodash.isEmpty(value) && lodash.includes(lodash.toUpper(movieData.title), lodash.toUpper(value))) {
found = true;
return false;
}
});
if (found || lodash.isEmpty(searchValues[0])) {
shouldRender = true;
}
}
else if (lodash.includes(lodash.toUpper(movieData.title), lodash.toUpper(this.searchValue))) {
shouldRender = true;
}
if (shouldRender) {
this.content.appendChild(movieElem);
count += 1;
}
if (lastRowTop !== movieElem.getBoundingClientRect().top) {
if (lastRowTop !== 0 && columnsCount === 0) {
columnsCount = count - 1;
}
lastRowTop = movieElem.getBoundingClientRect().top;
if (!isScrolledIntoView(movieElem) && !this.maxRenderCount) {
this.maxRenderCount = count - 1 + columnsCount * loadAdditionalRowsCount;
console.log(`Set max render count to ${this.maxRenderCount}`);
}
}
}
else {
return true;
}
});
}
const endElem = document.createElement('div'); const endElem = document.createElement('div');
endElem.className = 'clear'; endElem.className = 'clear';
this.content.appendChild(endElem); this.content.appendChild(endElem);
if ((!this.maxCount || count < this.maxCount) && !(!this.maxRenderCount || count < this.maxRenderCount)) { this.renderMovieElems();
this.content.appendChild(spinner);
}
this.calculatePositions(); this.calculatePositions();
this.loadCustomStyles(); this.loadCustomStyles();
}; };

@ -11,6 +11,10 @@ import style from './modules/style';
class PlexMeetsHomeAssistant extends HTMLElement { class PlexMeetsHomeAssistant extends HTMLElement {
plexProtocol: 'http' | 'https' = 'http'; plexProtocol: 'http' | 'https' = 'http';
columnsCount = 0;
renderedItems = 0;
plex: Plex | undefined; plex: Plex | undefined;
maxRenderCount: number | boolean = false; maxRenderCount: number | boolean = false;
@ -99,6 +103,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
loadInitialData = async (): Promise<void> => { loadInitialData = async (): Promise<void> => {
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {
const loadAdditionalRowsCount = 2; // todo: make this configurable
const height = Math.max( const height = Math.max(
document.body.scrollHeight, document.body.scrollHeight,
document.body.offsetHeight, document.body.offsetHeight,
@ -107,7 +112,10 @@ class PlexMeetsHomeAssistant extends HTMLElement {
document.documentElement.offsetHeight document.documentElement.offsetHeight
); );
if (window.innerHeight + window.scrollY > height - 300) { if (window.innerHeight + window.scrollY > height - 300) {
console.log('scrolled'); this.maxRenderCount = this.renderedItems - 1 + this.columnsCount * (loadAdditionalRowsCount * 2);
this.renderMovieElems();
this.calculatePositions();
} }
}); });
this.loading = true; this.loading = true;
@ -192,7 +200,65 @@ class PlexMeetsHomeAssistant extends HTMLElement {
return searchContainer; return searchContainer;
}; };
renderMovieElems = (): void => {
if (this.data[this.config.libraryName] && this.renderedItems < this.data[this.config.libraryName].length) {
let count = 0;
// eslint-disable-next-line consistent-return
const searchValues = _.split(this.searchValue, ' ');
// eslint-disable-next-line consistent-return
let lastRowTop = 0;
const loadAdditionalRowsCount = 2; // todo: make this configurable
// eslint-disable-next-line consistent-return
_.forEach(this.data[this.config.libraryName], (movieData: Record<string, any>) => {
if (
(!this.maxCount || this.renderedItems < this.maxCount) &&
(!this.maxRenderCount || this.renderedItems < this.maxRenderCount)
) {
const movieElem = this.getMovieElement(movieData);
let shouldRender = false;
if (this.looseSearch) {
let found = false;
// eslint-disable-next-line consistent-return
_.forEach(searchValues, value => {
if (!_.isEmpty(value) && _.includes(_.toUpper(movieData.title), _.toUpper(value))) {
found = true;
return false;
}
});
if (found || _.isEmpty(searchValues[0])) {
shouldRender = true;
}
} else if (_.includes(_.toUpper(movieData.title), _.toUpper(this.searchValue))) {
shouldRender = true;
}
if (shouldRender) {
count += 1;
if (count > this.renderedItems) {
this.content.appendChild(movieElem);
this.renderedItems += 1;
}
}
if (lastRowTop !== movieElem.getBoundingClientRect().top) {
if (lastRowTop !== 0 && this.columnsCount === 0) {
this.columnsCount = this.renderedItems - 1;
}
lastRowTop = movieElem.getBoundingClientRect().top;
if (!isScrolledIntoView(movieElem) && !this.maxRenderCount) {
this.maxRenderCount = this.renderedItems - 1 + this.columnsCount * loadAdditionalRowsCount;
console.log(`Set max render this.renderedItems to ${this.maxRenderCount}`);
}
}
} else {
return true;
}
});
}
};
renderPage = (): void => { renderPage = (): void => {
this.renderedItems = 0;
this.columnsCount = 0;
const spinner = document.createElement('div'); const spinner = document.createElement('div');
spinner.style.display = 'flex'; spinner.style.display = 'flex';
spinner.style.alignItems = 'center'; spinner.style.alignItems = 'center';
@ -224,7 +290,6 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
this.card.appendChild(this.content); this.card.appendChild(this.content);
let count = 0;
const contentbg = document.createElement('div'); const contentbg = document.createElement('div');
contentbg.className = 'contentbg'; contentbg.className = 'contentbg';
@ -260,64 +325,12 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.minimizeAll(); this.minimizeAll();
}); });
}, 1); }, 1);
if (this.data[this.config.libraryName]) {
// eslint-disable-next-line consistent-return
const searchValues = _.split(this.searchValue, ' ');
// eslint-disable-next-line consistent-return
let rowsRendered = 0;
let lastRowTop = 0;
let columnsCount = 0;
const loadAdditionalRowsCount = 2; // todo: make this configurable
// eslint-disable-next-line consistent-return
_.forEach(this.data[this.config.libraryName], (movieData: Record<string, any>) => {
if ((!this.maxCount || count < this.maxCount) && (!this.maxRenderCount || count < this.maxRenderCount)) {
const movieElem = this.getMovieElement(movieData);
let shouldRender = false;
if (this.looseSearch) {
let found = false;
// eslint-disable-next-line consistent-return
_.forEach(searchValues, value => {
if (!_.isEmpty(value) && _.includes(_.toUpper(movieData.title), _.toUpper(value))) {
found = true;
return false;
}
});
if (found || _.isEmpty(searchValues[0])) {
shouldRender = true;
}
} else if (_.includes(_.toUpper(movieData.title), _.toUpper(this.searchValue))) {
shouldRender = true;
}
if (shouldRender) {
this.content.appendChild(movieElem);
count += 1;
}
if (lastRowTop !== movieElem.getBoundingClientRect().top) {
if (lastRowTop !== 0 && columnsCount === 0) {
columnsCount = count - 1;
}
lastRowTop = movieElem.getBoundingClientRect().top;
rowsRendered += 1;
if (!isScrolledIntoView(movieElem) && !this.maxRenderCount) {
this.maxRenderCount = count - 1 + columnsCount * loadAdditionalRowsCount;
console.log(`Set max render count to ${this.maxRenderCount}`);
}
}
} else {
return true;
}
});
}
const endElem = document.createElement('div'); const endElem = document.createElement('div');
endElem.className = 'clear'; endElem.className = 'clear';
this.content.appendChild(endElem); this.content.appendChild(endElem);
if ((!this.maxCount || count < this.maxCount) && !(!this.maxRenderCount || count < this.maxRenderCount)) { this.renderMovieElems();
this.content.appendChild(spinner);
}
this.calculatePositions(); this.calculatePositions();
this.loadCustomStyles(); this.loadCustomStyles();
}; };

Loading…
Cancel
Save