Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.2 KiB

import { isElementInViewport } from "../lib/utils";
5 years ago
type LazyLoadElement = {
div: HTMLDivElement,
load: () => Promise<void>,
wasSeen?: boolean
};
export default class LazyLoadQueue {
5 years ago
private lazyLoadMedia: Array<LazyLoadElement> = [];
private loadingMedia = 0;
private tempID = 0;
5 years ago
private lockPromise: Promise<void> = null;
private unlockResolve: () => void = null;
private log = console.log.bind(console, '[LL]:');
5 years ago
constructor(private parallelLimit = 5) {
}
public clear() {
this.tempID--;
this.lazyLoadMedia.length = 0;
this.loadingMedia = 0;
}
5 years ago
public length() {
return this.lazyLoadMedia.length + this.loadingMedia;
}
public lock() {
if(this.lockPromise) return;
this.lockPromise = new Promise((resolve, reject) => {
this.unlockResolve = resolve;
});
}
public unlock() {
if(!this.unlockResolve) return;
this.lockPromise = null;
this.unlockResolve();
this.unlockResolve = null;
}
public async processQueue(id?: number) {
if(this.parallelLimit > 0 && this.loadingMedia >= this.parallelLimit) return;
5 years ago
let item: LazyLoadElement;
let index: number;
if(id !== undefined) item = this.lazyLoadMedia.splice(id, 1)[0];
else {
5 years ago
item = this.lazyLoadMedia.findAndSplice(i => isElementInViewport(i.div));
if(!item) {
let length = this.lazyLoadMedia.length;
for(index = length - 1; index >= 0; --index) {
if(this.lazyLoadMedia[index].wasSeen) {
item = this.lazyLoadMedia.splice(index, 1)[0];
break;
}
}
}
}
if(item) {
this.loadingMedia++;
let tempID = this.tempID;
this.log('will load media', this.lockPromise, item);
5 years ago
try {
5 years ago
if(this.lockPromise) {
let perf = performance.now();
await this.lockPromise;
this.log('waited lock:', performance.now() - perf);
5 years ago
}
await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));
await item.load();
} catch(err) {
console.error('loadMediaQueue error:', err, item, id, index);
}
if(tempID == this.tempID) {
this.loadingMedia--;
}
this.log('loaded media');
5 years ago
if(this.lazyLoadMedia.length) {
this.processQueue();
}
}
}
public check(id?: number) {
if(id !== undefined) {
5 years ago
let {div, wasSeen} = this.lazyLoadMedia[id];
if(!wasSeen && isElementInViewport(div)) {
//console.log('will load div by id:', div, div.getBoundingClientRect());
this.lazyLoadMedia[id].wasSeen = true;
this.processQueue(id);
}
return;
}
let length = this.lazyLoadMedia.length;
for(let i = length - 1; i >= 0; --i) {
5 years ago
let {div, wasSeen} = this.lazyLoadMedia[i];
5 years ago
if(!wasSeen && isElementInViewport(div)) {
//console.log('will load div:', div);
this.lazyLoadMedia[i].wasSeen = true;
this.processQueue(i);
//this.lazyLoadMedia.splice(i, 1);
}
}
}
5 years ago
public push(el: LazyLoadElement) {
let id = this.lazyLoadMedia.push(el) - 1;
5 years ago
if(el.wasSeen) {
this.processQueue(id);
} else {
el.wasSeen = false;
this.check(id);
}
}
}