mirror of
https://github.com/matrix-org/sliding-sync.git
synced 2025-03-10 13:37:11 +00:00
80 lines
3.2 KiB
JavaScript
80 lines
3.2 KiB
JavaScript
/**
|
|
* This file contains code for the room list DOM view. It controls rendering elements, the IntersectionObserver
|
|
* and lazy loading DOM nodes off-screen to ensure the list doesn't take O(n) to load.
|
|
*/
|
|
|
|
export class List {
|
|
/**
|
|
* Construct a new List. Children in this list MUST have `id=` attributes which contain sequential numbers.
|
|
* @param {string} idPrefix The prefix to remove from the `id=` attribute of children, if any.
|
|
* @param {number} debounceTime The number of milliseconds to wait before invoking the callback on intersection change.
|
|
* @param {function} callback The callback that will be invoked when the intersection has changed. It is called with
|
|
* args for the startIndex, endIndex (inclusive).
|
|
*/
|
|
constructor(idPrefix, debounceTime, callback) {
|
|
this.debounceTimeoutId = null;
|
|
this.debounceTime = debounceTime;
|
|
this.idPrefix = idPrefix;
|
|
this.visibleIndexes = {}; // e.g "44" meaning index 44
|
|
|
|
this.intersectionObserver = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
let key = entry.target.id.substring(this.idPrefix.length);
|
|
if (entry.isIntersecting) {
|
|
this.visibleIndexes[key] = true;
|
|
} else {
|
|
delete this.visibleIndexes[key];
|
|
}
|
|
});
|
|
// we will process the intersections after a short period of inactivity to not thrash the server
|
|
clearTimeout(this.debounceTimeoutId);
|
|
this.debounceTimeoutId = setTimeout(() => {
|
|
let startIndex = -1;
|
|
let endIndex = -1;
|
|
Object.keys(this.visibleIndexes).forEach((roomIndex) => {
|
|
// e.g "44"
|
|
let i = Number(roomIndex);
|
|
if (startIndex === -1 || i < startIndex) {
|
|
startIndex = i;
|
|
}
|
|
if (endIndex === -1 || i > endIndex) {
|
|
endIndex = i;
|
|
}
|
|
});
|
|
callback(startIndex, endIndex);
|
|
}, this.debounceTime);
|
|
},
|
|
{
|
|
threshold: [0],
|
|
}
|
|
);
|
|
}
|
|
|
|
resize(container, count, createElement) {
|
|
let addCount = 0;
|
|
let removeCount = 0;
|
|
// ensure we have the right number of children, remove or add appropriately.
|
|
while (container.childElementCount > count) {
|
|
this.intersectionObserver.unobserve(container.lastChild);
|
|
container.removeChild(container.lastChild);
|
|
removeCount += 1;
|
|
}
|
|
for (let i = container.childElementCount; i < count; i++) {
|
|
const cell = createElement(i);
|
|
container.appendChild(cell);
|
|
this.intersectionObserver.observe(cell);
|
|
addCount += 1;
|
|
}
|
|
if (addCount > 0 || removeCount > 0) {
|
|
console.log(
|
|
"resize: added ",
|
|
addCount,
|
|
"nodes, removed",
|
|
removeCount,
|
|
"nodes"
|
|
);
|
|
}
|
|
}
|
|
}
|