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.

142 lines
3.5 KiB

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import indexOfAndSplice from "../helpers/array/indexOfAndSplice";
import throttle from "../helpers/schedulers/throttle";
import { logger, LogTypes } from "../lib/logger";
const PARALLEL_LIMIT = 8;
export type LazyLoadElementBase = {
load: () => Promise<any>
};
export default class LazyLoadQueueBase {
public queueId = 0;
protected queue: Array<LazyLoadElementBase> = [];
protected inProcess: Set<LazyLoadElementBase> = new Set();
protected lockPromise: Promise<void> = null;
protected unlockResolve: () => void = null;
protected log = logger('LL', LogTypes.Error);
protected processQueue: () => void;
constructor(protected parallelLimit = PARALLEL_LIMIT) {
this.processQueue = throttle(() => this._processQueue(), 20, false);
}
public clear() {
this.inProcess.clear(); // ацтеки забьются, будет плохо
this.queue.length = 0;
// unreachable code
/* for(let item of this.inProcess) {
this.lazyLoadMedia.push(item);
} */
}
public lock() {
if(this.lockPromise) return;
//const perf = performance.now();
this.lockPromise = new Promise((resolve, reject) => {
this.unlockResolve = resolve;
});
/* if(DEBUG) {
this.lockPromise.then(() => {
this.log('was locked for:', performance.now() - perf);
});
} */
}
public unlock() {
if(!this.unlockResolve) return;
this.unlockResolve();
this.unlockResolve = this.lockPromise = null;
this.processQueue();
}
protected async processItem(item: LazyLoadElementBase) {
if(this.lockPromise) {
return;
}
this.inProcess.add(item);
/* if(DEBUG) {
this.log('will load media', this.lockPromise, item);
} */
try {
//await new Promise((resolve) => setTimeout(resolve, 2e3));
//await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));
//await item.load(item.div);
await this.loadItem(item);
} catch(err) {
if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(err as string)) {
this.log.error('loadMediaQueue error:', err/* , item */);
}
}
this.inProcess.delete(item);
/* if(DEBUG) {
this.log('loaded media', item);
} */
this.processQueue();
}
protected loadItem(item: LazyLoadElementBase) {
return item.load();
}
protected getItem() {
return this.queue.shift();
}
protected addElement(method: 'push' | 'unshift', el: LazyLoadElementBase) {
this.queue[method](el);
this.processQueue();
}
protected _processQueue(item?: LazyLoadElementBase) {
if(!this.queue.length || this.lockPromise || (this.parallelLimit > 0 && this.inProcess.size >= this.parallelLimit)) return;
//console.log('_processQueue start');
let added = 0;
do {
if(item) {
indexOfAndSplice(this.queue, item);
} else {
item = this.getItem();
}
if(item) {
this.processItem(item);
} else {
break;
}
item = null;
++added;
} while(this.inProcess.size < this.parallelLimit && this.queue.length);
//console.log('_processQueue end, added', added, this.queue.length);
}
public push(el: LazyLoadElementBase) {
this.addElement('push', el);
}
public unshift(el: LazyLoadElementBase) {
this.addElement('unshift', el);
}
}