Lazy load queue refactored

This commit is contained in:
morethanwords 2020-09-20 01:38:00 +03:00
parent 3cd6fb2928
commit 8b26d22cc4
23 changed files with 568 additions and 335 deletions

View File

@ -1,7 +1,7 @@
import appProfileManager from "../lib/appManagers/appProfileManager";
import { $rootScope } from "../lib/utils";
$rootScope.$on('avatar_update', (e: CustomEvent) => {
$rootScope.$on('avatar_update', (e) => {
let peerID = e.detail;
appProfileManager.removeFromAvatarsCache(peerID);

View File

@ -46,7 +46,7 @@ export class ChatAudio {
appMediaPlaybackController.toggle();
});
$rootScope.$on('audio_play', (e: CustomEvent) => {
$rootScope.$on('audio_play', (e) => {
const {doc, mid} = e.detail;
let title: string, subtitle: string;

View File

@ -81,7 +81,7 @@ export class EmoticonsDropdown {
}
clearTimeout(this.displayTimeout);
this.displayTimeout = setTimeout(() => {
this.displayTimeout = window.setTimeout(() => {
this.toggle(false);
}, 200);
};
@ -188,7 +188,7 @@ export class EmoticonsDropdown {
if((this.element.style.display && enable === undefined) || enable) {
this.events.onOpen.forEach(cb => cb());
EmoticonsDropdown.lazyLoadQueue.lockIntersection();
EmoticonsDropdown.lazyLoadQueue.lock();
//EmoticonsDropdown.lazyLoadQueue.unlock();
animationIntersector.lockIntersectionGroup(EMOTICONSSTICKERGROUP);
@ -197,9 +197,10 @@ export class EmoticonsDropdown {
this.element.classList.add('active');
clearTimeout(this.displayTimeout);
this.displayTimeout = setTimeout(() => {
this.displayTimeout = window.setTimeout(() => {
animationIntersector.unlockIntersectionGroup(EMOTICONSSTICKERGROUP);
EmoticonsDropdown.lazyLoadQueue.unlockIntersection();
EmoticonsDropdown.lazyLoadQueue.unlock();
EmoticonsDropdown.lazyLoadQueue.refresh();
this.events.onOpenAfter.forEach(cb => cb());
}, touchSupport ? 0 : 200);
@ -210,7 +211,7 @@ export class EmoticonsDropdown {
} else {
this.events.onClose.forEach(cb => cb());
EmoticonsDropdown.lazyLoadQueue.lockIntersection();
EmoticonsDropdown.lazyLoadQueue.lock();
//EmoticonsDropdown.lazyLoadQueue.lock();
// нужно залочить группу и выключить стикеры
@ -220,12 +221,13 @@ export class EmoticonsDropdown {
this.element.classList.remove('active');
clearTimeout(this.displayTimeout);
this.displayTimeout = setTimeout(() => {
this.displayTimeout = window.setTimeout(() => {
this.element.style.display = 'none';
// теперь можно убрать visible, чтобы они не включились после фокуса
animationIntersector.unlockIntersectionGroup(EMOTICONSSTICKERGROUP);
EmoticonsDropdown.lazyLoadQueue.unlockIntersection();
EmoticonsDropdown.lazyLoadQueue.unlock();
EmoticonsDropdown.lazyLoadQueue.refresh();
this.events.onCloseAfter.forEach(cb => cb());
}, touchSupport ? 0 : 200);

View File

@ -13,6 +13,7 @@ import apiManager from "../../../lib/mtproto/mtprotoworker";
import StickyIntersector from "../../stickyIntersector";
import appDocsManager, {MyDocument} from "../../../lib/appManagers/appDocsManager";
import animationIntersector from "../../animationIntersector";
import LazyLoadQueue, { LazyLoadQueueRepeat } from "../../lazyLoadQueue";
export default class StickersTab implements EmoticonsTab {
public content: HTMLElement;
@ -36,7 +37,7 @@ export default class StickersTab implements EmoticonsTab {
private stickyIntersector: StickyIntersector;
private animatedDivs: Set<HTMLDivElement> = new Set();
private animatedIntersector: IntersectionObserver;
private lazyLoadQueue: LazyLoadQueueRepeat;
categoryPush(categoryDiv: HTMLElement, categoryTitle: string, promise: Promise<MyDocument[]>, prepend?: boolean) {
//if((docs.length % 5) != 0) categoryDiv.classList.add('not-full');
@ -83,7 +84,11 @@ export default class StickersTab implements EmoticonsTab {
if(doc.sticker == 2) {
this.animatedDivs.add(div);
this.animatedIntersector.observe(div);
this.lazyLoadQueue.observe({
div,
load: this.processVisibleDiv
});
}
}
@ -163,6 +168,58 @@ export default class StickersTab implements EmoticonsTab {
}
}
checkAnimationContainer = (div: HTMLElement, visible: boolean) => {
//console.error('checkAnimationContainer', div, visible);
const players = animationIntersector.getAnimations(div);
players.forEach(player => {
if(!visible) {
animationIntersector.checkAnimation(player, true, true);
} else {
animationIntersector.checkAnimation(player, false);
}
});
};
processVisibleDiv = (div: HTMLElement) => {
const docID = div.dataset.docID;
const doc = appDocsManager.getDoc(docID);
const promise = wrapSticker({
doc,
div: div as HTMLDivElement,
width: 80,
height: 80,
lazyLoadQueue: null,
group: EMOTICONSSTICKERGROUP,
onlyThumb: false,
play: true,
loop: true
});
promise.then(() => {
//clearTimeout(timeout);
this.checkAnimationContainer(div, this.lazyLoadQueue.intersector.isVisible(div));
});
/* let timeout = window.setTimeout(() => {
console.error('processVisibleDiv timeout', div, doc);
}, 1e3); */
return promise;
};
processInvisibleDiv = (div: HTMLElement) => {
const docID = div.dataset.docID;
const doc = appDocsManager.getDoc(docID);
//console.log('STICKER INvisible:', /* div, */docID);
this.checkAnimationContainer(div, false);
div.innerHTML = '';
this.renderSticker(doc, div as HTMLDivElement);
};
init() {
this.content = document.getElementById('content-stickers');
//let stickersDiv = contentStickersDiv.querySelector('.os-content') as HTMLDivElement;
@ -196,7 +253,7 @@ export default class StickersTab implements EmoticonsTab {
}
}); */
$rootScope.$on('stickers_installed', (e: CustomEvent) => {
$rootScope.$on('stickers_installed', (e) => {
const set: StickerSet.stickerSet = e.detail;
if(!this.stickerSets[set.id] && this.mounted) {
@ -204,7 +261,7 @@ export default class StickersTab implements EmoticonsTab {
}
});
$rootScope.$on('stickers_deleted', (e: CustomEvent) => {
$rootScope.$on('stickers_deleted', (e) => {
const set: StickerSet.stickerSet = e.detail;
if(this.stickerSets[set.id] && this.mounted) {
@ -256,98 +313,59 @@ export default class StickersTab implements EmoticonsTab {
this.mounted = true;
});
const checkAnimationDiv = (div: HTMLDivElement) => {
const players = animationIntersector.getAnimations(div);
players.forEach(player => {
if(!visible.has(div)) {
animationIntersector.checkAnimation(player, true, true);
} else {
animationIntersector.checkAnimation(player, false);
}
});
};
const processInvisibleDiv = (div: HTMLDivElement) => {
visible.delete(div);
//console.log('STICKER INvisible:', target, docID);
const docID = div.dataset.docID;
const doc = appDocsManager.getDoc(docID);
checkAnimationDiv(div);
div.innerHTML = '';
this.renderSticker(doc, div);
};
let locked = false;
const visible: Set<HTMLDivElement> = new Set();
this.animatedIntersector = new IntersectionObserver((entries) => {
if(locked) {
return;
this.lazyLoadQueue = new LazyLoadQueueRepeat(undefined, (target, visible) => {
if(!visible) {
this.processInvisibleDiv(target as HTMLDivElement);
}
entries.forEach(entry => {
const {target, isIntersecting} = entry;
const div = target as HTMLDivElement;
const docID = div.dataset.docID;
const doc = appDocsManager.getDoc(docID);
if(isIntersecting) {
//console.log('STICKER visible:', target, docID);
if(visible.has(div)) {
return;
}
visible.add(div);
wrapSticker({
doc,
div,
width: 80,
height: 80,
lazyLoadQueue: null,
group: EMOTICONSSTICKERGROUP,
onlyThumb: false,
play: true,
loop: true
}).then(() => {
checkAnimationDiv(div);
});
} else {
processInvisibleDiv(div);
}
});
//animationIntersector.checkAnimations(true, EMOTICONSSTICKERGROUP, false);
});
/* let closed = true;
emoticonsDropdown.events.onClose.push(() => {
locked = true;
closed = false;
this.lazyLoadQueue.lock();
});
emoticonsDropdown.events.onCloseAfter.push(() => {
const divs = [...visible];
const divs = this.lazyLoadQueue.intersector.getVisible();
for(const div of divs) {
processInvisibleDiv(div);
this.processInvisibleDiv(div);
}
closed = true;
});
emoticonsDropdown.events.onOpenAfter.push(() => {
locked = false;
// refresh
this.animatedIntersector.disconnect();
const divs = [...this.animatedDivs];
for(const div of divs) {
this.animatedIntersector.observe(div);
if(closed) {
this.lazyLoadQueue.unlockAndRefresh();
closed = false;
} else {
this.lazyLoadQueue.unlock();
}
}); */
emoticonsDropdown.events.onClose.push(() => {
this.lazyLoadQueue.lock();
});
emoticonsDropdown.events.onCloseAfter.push(() => {
const divs = this.lazyLoadQueue.intersector.getVisible();
for(const div of divs) {
this.processInvisibleDiv(div);
}
this.lazyLoadQueue.intersector.clearVisible();
});
emoticonsDropdown.events.onOpenAfter.push(() => {
this.lazyLoadQueue.unlockAndRefresh();
});
/* setInterval(() => {
// @ts-ignore
console.log('STICKERS RENDERED IN PANEL:', Object.values(lottieLoader.players).filter(p => p.width == 80).length);
const players = Object.values(lottieLoader.players).filter(p => p.width == 80);
console.log('STICKERS RENDERED IN PANEL:', players.length, players.filter(p => !p.paused).length, this.lazyLoadQueue.intersector.getVisible().length);
}, .25e3); */

View File

@ -1,67 +1,35 @@
import { logger, LogLevels } from "../lib/logger";
import VisibilityIntersector, { OnVisibilityChange } from "./visibilityIntersector";
type LazyLoadElement = {
type LazyLoadElementBase = {
div: HTMLDivElement,
load: () => Promise<any>,
load: (target?: HTMLDivElement) => Promise<any>
};
type LazyLoadElement = LazyLoadElementBase & {
wasSeen?: boolean
};
export default class LazyLoadQueue {
private lazyLoadMedia: Array<LazyLoadElement> = [];
private inProcess: Array<LazyLoadElement> = [];
export class LazyLoadQueueBase {
protected lazyLoadMedia: Array<LazyLoadElementBase> = [];
protected inProcess: Set<LazyLoadElementBase> = new Set();
private lockPromise: Promise<void> = null;
private unlockResolve: () => void = null;
protected lockPromise: Promise<void> = null;
protected unlockResolve: () => void = null;
private log = logger('LL', LogLevels.error);
protected log = logger('LL', LogLevels.error);
// Observer will call entry only 1 time per element
private observer: IntersectionObserver;
private intersectionLocked = false;
constructor(private parallelLimit = 5, private noObserver = false) {
if(noObserver) return;
this.observer = new IntersectionObserver(entries => {
if(this.lockPromise || this.intersectionLocked) return;
const intersecting = entries.filter(entry => entry.isIntersecting);
intersecting.forEachReverse(entry => {
const target = entry.target as HTMLElement;
this.log('isIntersecting', target);
// need for set element first if scrolled
const item = this.lazyLoadMedia.findAndSplice(i => i.div == target);
if(item) {
item.wasSeen = true;
this.lazyLoadMedia.unshift(item);
//this.processQueue(item);
}
});
if(intersecting.length) {
this.processQueue();
}
});
constructor(protected parallelLimit = 5) {
}
public clear() {
this.inProcess.length = 0; // ацтеки забьются, будет плохо
this.inProcess.clear(); // ацтеки забьются, будет плохо
this.lazyLoadMedia.length = 0;
for(let item of this.inProcess) {
// unreachable code
/* for(let item of this.inProcess) {
this.lazyLoadMedia.push(item);
}
if(this.observer) {
this.observer.disconnect();
}
}
public length() {
return this.lazyLoadMedia.length + this.inProcess.length;
} */
}
public lock() {
@ -78,92 +46,200 @@ export default class LazyLoadQueue {
this.unlockResolve = null;
}
public async processQueue(item?: LazyLoadElement) {
if(this.parallelLimit > 0 && this.inProcess.length >= this.parallelLimit) return;
public async processItem(item: LazyLoadElementBase) {
this.inProcess.add(item);
if(item) {
this.lazyLoadMedia.findAndSplice(i => i == item);
} else {
item = this.lazyLoadMedia.findAndSplice(i => i.wasSeen);
this.log('will load media', this.lockPromise, item);
try {
if(this.lockPromise/* && false */) {
const perf = performance.now();
await this.lockPromise;
this.log('waited lock:', performance.now() - perf);
}
//await new Promise((resolve) => setTimeout(resolve, 2e3));
//await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));
await item.load(item.div);
} catch(err) {
this.log.error('loadMediaQueue error:', err/* , item */);
}
if(item) {
this.inProcess.push(item);
this.inProcess.delete(item);
this.log('will load media', this.lockPromise, item);
this.log('loaded media', item);
try {
if(this.lockPromise/* && false */) {
let perf = performance.now();
await this.lockPromise;
this.log('waited lock:', performance.now() - perf);
}
//await new Promise((resolve) => setTimeout(resolve, 2e3));
//await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));
await item.load();
} catch(err) {
this.log.error('loadMediaQueue error:', err/* , item */);
}
if(!this.noObserver) {
this.observer.unobserve(item.div);
}
this.inProcess.findAndSplice(i => i == item);
this.log('loaded media', item);
if(this.lazyLoadMedia.length) {
this.processQueue();
}
if(this.lazyLoadMedia.length) {
this.processQueue();
}
}
public addElement(el: LazyLoadElement) {
if(el.wasSeen) {
this.processQueue(el);
} else {
el.wasSeen = false;
if(this.observer) {
this.observer.observe(el.div);
}
}
protected getItem() {
return this.lazyLoadMedia.shift();
}
protected addElement(el: LazyLoadElementBase) {
this.processQueue(el);
}
public async processQueue(item?: LazyLoadElementBase) {
if(this.parallelLimit > 0 && this.inProcess.size >= this.parallelLimit) return;
do {
if(item) {
this.lazyLoadMedia.findAndSplice(i => i == item);
} else {
item = this.getItem();
}
public push(el: LazyLoadElement) {
if(item) {
this.processItem(item);
} else {
break;
}
item = null;
} while(this.inProcess.size < this.parallelLimit && this.lazyLoadMedia.length);
}
public push(el: LazyLoadElementBase) {
this.lazyLoadMedia.push(el);
this.addElement(el);
}
public unshift(el: LazyLoadElement) {
public unshift(el: LazyLoadElementBase) {
this.lazyLoadMedia.unshift(el);
this.addElement(el);
}
}
export class LazyLoadQueueIntersector extends LazyLoadQueueBase {
public intersector: VisibilityIntersector;
protected intersectorTimeout: number;
constructor(protected parallelLimit = 5) {
super(parallelLimit);
}
public lock() {
super.lock();
this.intersector.lock();
}
public unlock() {
super.unlock();
this.intersector.unlock();
}
public unlockAndRefresh() {
super.unlock();
this.intersector.unlockAndRefresh();
}
public clear() {
super.clear();
this.intersector.disconnect();
}
public refresh() {
const items = this.lazyLoadMedia;
if(items && items.length) {
items.forEach(item => {
this.observer.unobserve(item.div);
});
this.intersector.refresh();
}
window.requestAnimationFrame(() => {
items.forEach(item => {
this.observer.observe(item.div);
});
});
protected setProcessQueueTimeout() {
if(!this.intersectorTimeout) {
this.intersectorTimeout = window.setTimeout(() => {
this.intersectorTimeout = 0;
this.processQueue();
}, 0);
}
}
}
export default class LazyLoadQueue extends LazyLoadQueueIntersector {
protected lazyLoadMedia: Array<LazyLoadElement> = [];
protected inProcess: Set<LazyLoadElement> = new Set();
constructor(protected parallelLimit = 5) {
super(parallelLimit);
this.intersector = new VisibilityIntersector(this.onVisibilityChange);
}
private onVisibilityChange = (target: HTMLElement, visible: boolean) => {
if(visible) {
this.log('isIntersecting', target);
// need for set element first if scrolled
const item = this.lazyLoadMedia.findAndSplice(i => i.div == target);
if(item) {
item.wasSeen = true;
this.lazyLoadMedia.unshift(item);
//this.processQueue(item);
}
this.setProcessQueueTimeout();
}
};
protected getItem() {
return this.lazyLoadMedia.findAndSplice(item => item.wasSeen);
}
public async processItem(item: LazyLoadElement) {
await super.processItem(item);
this.intersector.unobserve(item.div);
}
protected addElement(el: LazyLoadElement) {
//super.addElement(el);
if(el.wasSeen) {
super.processQueue(el);
} else {
el.wasSeen = false;
this.intersector.observe(el.div);
}
}
public lockIntersection() {
this.intersectionLocked = true;
public push(el: LazyLoadElement) {
super.push(el);
}
public unlockIntersection() {
this.intersectionLocked = false;
this.refresh();
public unshift(el: LazyLoadElement) {
super.unshift(el);
}
}
export class LazyLoadQueueRepeat extends LazyLoadQueueIntersector {
private _lazyLoadMedia: Map<HTMLElement, LazyLoadElementBase> = new Map();
constructor(protected parallelLimit = 5, protected onVisibilityChange?: OnVisibilityChange) {
super(parallelLimit);
this.intersector = new VisibilityIntersector((target, visible) => {
if(visible) {
const item = this.lazyLoadMedia.findAndSplice(i => i.div == target);
this.lazyLoadMedia.unshift(item || this._lazyLoadMedia.get(target));
} else {
this.lazyLoadMedia.findAndSplice(i => i.div == target);
}
this.onVisibilityChange && this.onVisibilityChange(target, visible);
this.setProcessQueueTimeout();
});
}
/* public async processItem(item: LazyLoadElement) {
//await super.processItem(item);
await LazyLoadQueueBase.prototype.processItem.call(this, item);
if(this.lazyLoadMedia.length) {
this.processQueue();
}
} */
public observe(el: LazyLoadElementBase) {
this._lazyLoadMedia.set(el.div, el);
this.intersector.observe(el.div);
}
}

View File

@ -155,6 +155,19 @@ let closeBtnMenu = () => {
window.removeEventListener('contextmenu', onClick);
};
window.addEventListener('resize', () => {
if(openedMenu) {
closeBtnMenu();
}
/* if(openedMenu && (openedMenu.style.top || openedMenu.style.left)) {
const rect = openedMenu.getBoundingClientRect();
const {innerWidth, innerHeight} = window;
console.log(innerWidth, innerHeight, rect);
} */
});
let openedMenu: HTMLDivElement = null, openedMenuOnClose: () => void = null;
export function openBtnMenu(menuElement: HTMLDivElement, onClose?: () => void) {
closeBtnMenu();
@ -248,7 +261,7 @@ export function attachContextMenuListener(element: HTMLElement, callback: (e: To
}
}; */
timeout = setTimeout(() => {
timeout = window.setTimeout(() => {
callback(e.touches[0]);
onCancel();

View File

@ -63,7 +63,7 @@ export const roundPercents = (percents: number[]) => {
};
const connectedPolls: {id: string, element: PollElement}[] = [];
$rootScope.$on('poll_update', (e: CustomEvent) => {
$rootScope.$on('poll_update', (e) => {
const {poll, results} = e.detail as {poll: Poll, results: PollResults};
//console.log('poll_update', poll, results);
@ -123,7 +123,7 @@ const setQuizHint = (solution: string, solution_entities: any[], onHide: () => v
prevQuizHint = element;
prevQuizHintOnHide = onHide;
prevQuizHintTimeout = setTimeout(() => {
prevQuizHintTimeout = window.setTimeout(() => {
hideQuizHint(element, onHide, prevQuizHintTimeout);
}, touchSupport ? 5000 : 7000);
};
@ -280,7 +280,7 @@ export default class PollElement extends HTMLElement {
// circle.style.strokeDashoffset = circumference + percents * circumference;
// circle.style.strokeDasharray = ${circumference} ${circumference};
this.quizInterval = setInterval(() => {
this.quizInterval = window.setInterval(() => {
const time = Date.now();
const percents = (closeTime - time) / period;
const timeLeft = (closeTime - time) / 1000 + 1 | 0;

View File

@ -118,8 +118,8 @@ export default class AppChatFoldersTab implements SliderTab {
}
});
$rootScope.$on('filter_update', (e: CustomEvent) => {
const filter: DialogFilter = e.detail;
$rootScope.$on('filter_update', (e) => {
const filter = e.detail;
if(this.filtersRendered.hasOwnProperty(filter.id)) {
this.renderFolder(filter, null, this.filtersRendered[filter.id]);
} else {
@ -129,8 +129,8 @@ export default class AppChatFoldersTab implements SliderTab {
this.getSuggestedFilters();
});
$rootScope.$on('filter_delete', (e: CustomEvent) => {
const filter: DialogFilter = e.detail;
$rootScope.$on('filter_delete', (e) => {
const filter = e.detail;
if(this.filtersRendered.hasOwnProperty(filter.id)) {
/* for(const suggested of this.suggestedFilters) {
if(deepEqual(suggested.filter, filter)) {

View File

@ -26,7 +26,7 @@ export default class AppSettingsTab implements SliderTab {
constructor() {
parseMenuButtonsTo(this.buttons, this.container.querySelector('.profile-buttons').children);
$rootScope.$on('user_auth', (e: CustomEvent) => {
$rootScope.$on('user_auth', (e) => {
this.fillElements();
});

View File

@ -0,0 +1,117 @@
type TargetType = HTMLElement;
export type OnVisibilityChange = (target: TargetType, visible: boolean) => void;
export default class VisibilityIntersector {
private observer: IntersectionObserver;
private items: Map<TargetType, boolean> = new Map();
private locked = false;
constructor(onVisibilityChange: OnVisibilityChange) {
this.observer = new IntersectionObserver((entries) => {
if(this.locked) {
return;
}
const changed: {target: TargetType, visible: boolean}[] = [];
entries.forEach(entry => {
const target = entry.target as TargetType;
if(this.items.get(target) == entry.isIntersecting) {
return;
} else {
this.items.set(target, entry.isIntersecting);
}
/* if(entry.isIntersecting) {
console.log('ooo', entry);
} */
/* if(this.locked) {
return;
} */
changed[entry.isIntersecting ? 'unshift' : 'push']({target, visible: entry.isIntersecting});
//onVisibilityChange(target, entry.isIntersecting);
});
changed.forEach(smth => {
onVisibilityChange(smth.target, smth.visible);
});
});
}
public getVisible() {
const items: TargetType[] = [];
this.items.forEach((value, key) => {
if(value) {
items.push(key);
}
});
return items;
}
public clearVisible() {
const visible = this.getVisible();
for(const target of visible) {
this.items.set(target, false);
}
}
public isVisible(target: TargetType) {
return this.items.get(target);
}
public disconnect() {
this.observer.disconnect();
this.items.clear();
}
public refresh() {
this.observer.disconnect();
//window.requestAnimationFrame(() => {
const targets = [...this.items.keys()];
for(const target of targets) {
//this.items.set(target, false);
this.observer.observe(target);
}
//});
}
public refreshVisible() {
const visible = this.getVisible();
for(const target of visible) {
this.observer.unobserve(target);
}
for(const target of visible) {
this.observer.observe(target);
}
}
public observe(target: TargetType) {
this.items.set(target, false);
this.observer.observe(target);
}
public unobserve(target: TargetType) {
this.observer.unobserve(target);
this.items.delete(target);
}
public unlock() {
this.locked = false;
}
public unlockAndRefresh() {
this.unlock();
this.refresh();
}
public lock() {
this.locked = true;
}
}

View File

@ -18,6 +18,7 @@ import webpWorkerController from '../lib/webp/webpWorkerController';
import { readBlobAsText } from '../helpers/blob';
import appMediaPlaybackController from './appMediaPlaybackController';
import { PhotoSize } from '../layer';
import { deferredPromise } from '../lib/polyfill';
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group}: {
doc: MyDocument,
@ -595,12 +596,12 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
//appDocsManager.downloadDocNew(doc.id).promise.then(res => res.json()).then(async(json) => {
//fetch(doc.url).then(res => res.json()).then(async(json) => {
await appDocsManager.downloadDocNew(doc)
/* return */ await appDocsManager.downloadDocNew(doc)
.then(readBlobAsText)
.then(JSON.parse)
.then(async(json) => {
//console.timeEnd('download sticker' + doc.id);
//console.log('loaded sticker:', doc, div, blob);
//console.log('loaded sticker:', doc, div/* , blob */);
if(middleware && !middleware()) return;
let animation = await LottieLoader.loadAnimationWorker/* loadAnimation */({
@ -611,6 +612,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
width,
height
}, group, toneIndex);
//const deferred = deferredPromise<void>();
animation.addListener('firstFrame', () => {
if(div.firstElementChild && div.firstElementChild.tagName == 'IMG') {
@ -618,6 +621,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
} else {
animation.canvas.classList.add('fade-in');
}
//deferred.resolve();
}, true);
if(emoji) {
@ -629,6 +634,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
}
});
}
//return deferred;
//await new Promise((resolve) => setTimeout(resolve, 5e3));
});

View File

@ -68,7 +68,7 @@ export class AppChatsManager {
public megagroupOnlines: {[id: number]: {timestamp: number, onlines: number}} = {};
constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
// console.log('on apiUpdate', update)
const update = e.detail;
switch(update._) {

View File

@ -424,7 +424,7 @@ export class AppDialogsManager {
(window as any).addElement = add;
} */
$rootScope.$on('user_update', (e: CustomEvent) => {
$rootScope.$on('user_update', (e) => {
let userID = e.detail;
let user = appUsersManager.getUser(userID);
@ -450,7 +450,7 @@ export class AppDialogsManager {
}
});
$rootScope.$on('dialog_top', (e: CustomEvent) => {
$rootScope.$on('dialog_top', (e) => {
let dialog: any = e.detail;
this.setLastMessage(dialog);
@ -460,7 +460,7 @@ export class AppDialogsManager {
this.setFiltersUnreadCount();
});
$rootScope.$on('dialog_flush', (e: CustomEvent) => {
$rootScope.$on('dialog_flush', (e) => {
let peerID: number = e.detail.peerID;
let dialog = appMessagesManager.getDialogByPeerID(peerID)[0];
if(dialog) {
@ -470,7 +470,7 @@ export class AppDialogsManager {
}
});
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
$rootScope.$on('dialogs_multiupdate', (e) => {
const dialogs = e.detail;
for(const id in dialogs) {
@ -483,7 +483,7 @@ export class AppDialogsManager {
this.setFiltersUnreadCount();
});
$rootScope.$on('dialog_drop', (e: CustomEvent) => {
$rootScope.$on('dialog_drop', (e) => {
let {peerID, dialog} = e.detail;
let dom = this.getDialogDom(peerID);
@ -496,11 +496,8 @@ export class AppDialogsManager {
this.setFiltersUnreadCount();
});
$rootScope.$on('dialog_unread', (e: CustomEvent) => {
let info: {
peerID: number,
count: number
} = e.detail;
$rootScope.$on('dialog_unread', (e) => {
let info = e.detail;
let dialog = appMessagesManager.getDialogByPeerID(info.peerID)[0];
if(dialog) {
@ -522,7 +519,7 @@ export class AppDialogsManager {
}
});
$rootScope.$on('peer_changed', (e: CustomEvent) => {
$rootScope.$on('peer_changed', (e) => {
let peerID = e.detail;
let lastPeerID = this.lastActiveListElement && +this.lastActiveListElement.getAttribute('data-peerID');
@ -540,7 +537,7 @@ export class AppDialogsManager {
}
});
$rootScope.$on('filter_update', (e: CustomEvent) => {
$rootScope.$on('filter_update', (e) => {
const filter: DialogFilter = e.detail;
if(!this.filtersRendered[filter.id]) {
this.addFilter(filter);
@ -560,7 +557,7 @@ export class AppDialogsManager {
elements.title.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
});
$rootScope.$on('filter_delete', (e: CustomEvent) => {
$rootScope.$on('filter_delete', (e) => {
const filter: DialogFilter = e.detail;
const elements = this.filtersRendered[filter.id];
if(!elements) return;
@ -580,7 +577,7 @@ export class AppDialogsManager {
}
});
/* $rootScope.$on('filter_pinned_order', (e: CustomEvent) => {
/* $rootScope.$on('filter_pinned_order', (e) => {
const {order, id} = e.detail as {order: number[], id: number};
if(this.prevTabID != id) {
return;

View File

@ -154,13 +154,13 @@ export class AppImManager {
this.myID = $rootScope.myID = id;
});
$rootScope.$on('user_auth', (e: CustomEvent) => {
$rootScope.$on('user_auth', (e) => {
let userAuth = e.detail;
this.myID = $rootScope.myID = userAuth ? userAuth.id : 0;
});
// will call when message is sent (only 1)
$rootScope.$on('history_append', (e: CustomEvent) => {
$rootScope.$on('history_append', (e) => {
let details = e.detail;
if(!this.scrolledAllDown) {
@ -171,7 +171,7 @@ export class AppImManager {
});
// will call when sent for update pos
$rootScope.$on('history_update', (e: CustomEvent) => {
$rootScope.$on('history_update', (e) => {
let details = e.detail;
if(details.mid && details.peerID == this.peerID) {
@ -192,7 +192,7 @@ export class AppImManager {
}
});
$rootScope.$on('history_multiappend', (e: CustomEvent) => {
$rootScope.$on('history_multiappend', (e) => {
let msgIDsByPeer = e.detail;
if(!(this.peerID in msgIDsByPeer)) return;
@ -201,23 +201,20 @@ export class AppImManager {
this.renderNewMessagesByIDs(msgIDs);
});
$rootScope.$on('history_delete', (e: CustomEvent) => {
let detail: {
peerID: string,
msgs: {[x: number]: boolean}
} = e.detail;
$rootScope.$on('history_delete', (e) => {
let detail = e.detail;
this.deleteMessagesByIDs(Object.keys(detail.msgs).map(s => +s));
});
$rootScope.$on('dialog_flush', (e: CustomEvent) => {
$rootScope.$on('dialog_flush', (e) => {
let peerID: number = e.detail.peerID;
if(this.peerID == peerID) {
this.deleteMessagesByIDs(Object.keys(this.bubbles).map(m => +m));
}
});
$rootScope.$on('chat_update', (e: CustomEvent) => {
$rootScope.$on('chat_update', (e) => {
const peerID: number = e.detail;
if(this.peerID == -peerID) {
const chat = appChatsManager.getChat(peerID) as Channel | Chat;
@ -227,7 +224,7 @@ export class AppImManager {
});
// Calls when message successfully sent and we have an ID
$rootScope.$on('message_sent', (e: CustomEvent) => {
$rootScope.$on('message_sent', (e) => {
const {tempID, mid} = e.detail;
this.log('message_sent', e.detail);
@ -236,14 +233,14 @@ export class AppImManager {
const message = appMessagesManager.getMessage(mid);
if(message.media) {
if(message.media.photo) {
const photo = appPhotosManager.getPhoto(tempID);
const photo = appPhotosManager.getPhoto('' + tempID);
if(/* photo._ != 'photoEmpty' */photo) {
const newPhoto = message.media.photo;
newPhoto.downloaded = photo.downloaded;
newPhoto.url = photo.url;
}
} else if(message.media.document) {
const doc = appDocsManager.getDoc(tempID);
const doc = appDocsManager.getDoc('' + tempID);
if(/* doc._ != 'documentEmpty' && */doc?.type && doc.type != 'sticker') {
const newDoc = message.media.document;
newDoc.downloaded = doc.downloaded;
@ -272,7 +269,7 @@ export class AppImManager {
const pollElement = bubble.querySelector('poll-element');
if(pollElement) {
pollElement.setAttribute('poll-id', newPoll.id);
pollElement.setAttribute('message-id', mid);
pollElement.setAttribute('message-id', '' + mid);
delete appPollsManager.polls[tempID];
delete appPollsManager.results[tempID];
}
@ -286,7 +283,7 @@ export class AppImManager {
bubble.classList.remove('is-sending');
bubble.classList.add('is-sent');
bubble.dataset.mid = mid;
bubble.dataset.mid = '' + mid;
this.bubbleGroups.removeBubble(bubble, tempID);
@ -301,7 +298,7 @@ export class AppImManager {
}
});
$rootScope.$on('message_edit', (e: CustomEvent) => {
$rootScope.$on('message_edit', (e) => {
let {peerID, mid, id, justMedia} = e.detail;
if(peerID != this.peerID) return;
@ -318,7 +315,7 @@ export class AppImManager {
this.renderMessage(message, true, false, bubble, false);
});
$rootScope.$on('messages_downloaded', (e: CustomEvent) => {
$rootScope.$on('messages_downloaded', (e) => {
const mids: number[] = e.detail;
const pinnedMessage = appMessagesManager.getPinnedMessage(this.peerID);
@ -351,7 +348,7 @@ export class AppImManager {
});
});
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
let update = e.detail;
this.handleUpdate(update);

View File

@ -9,7 +9,7 @@ import appDocsManager, {MyDocument} from "./appDocsManager";
import VideoPlayer from "../mediaPlayer";
import { renderImageFromUrl, parseMenuButtonsTo } from "../../components/misc";
import AvatarElement from "../../components/avatar";
import LazyLoadQueue from "../../components/lazyLoadQueue";
import LazyLoadQueue, { LazyLoadQueueBase } from "../../components/lazyLoadQueue";
import appForward from "../../components/appForward";
import { isSafari, mediaSizes, touchSupport } from "../config";
import { deferredPromise } from "../polyfill";
@ -118,7 +118,7 @@ export class AppMediaViewer {
private setMoverPromise: Promise<void>;
private setMoverAnimationPromise: Promise<void>;
private lazyLoadQueue: LazyLoadQueue;
private lazyLoadQueue: LazyLoadQueueBase;
private highlightSwitchersTimeout: number;
@ -128,7 +128,7 @@ export class AppMediaViewer {
this.preloaderStreamable = new ProgressivePreloader(undefined, false, true);
this.lazyLoadQueue = new LazyLoadQueue(undefined, true);
this.lazyLoadQueue = new LazyLoadQueueBase();
parseMenuButtonsTo(this.buttons, this.wholeDiv.querySelectorAll(`[class*='menu']`) as NodeListOf<HTMLElement>);
@ -271,7 +271,7 @@ export class AppMediaViewer {
this.wholeDiv.classList.add('highlight-switchers');
}
this.highlightSwitchersTimeout = setTimeout(() => {
this.highlightSwitchersTimeout = window.setTimeout(() => {
this.wholeDiv.classList.remove('highlight-switchers');
this.highlightSwitchersTimeout = 0;
}, 3e3);
@ -1075,8 +1075,7 @@ export class AppMediaViewer {
this.lazyLoadQueue.unshift({
div: null,
load,
wasSeen: true
load
});
//} else createPlayer();
});
@ -1140,8 +1139,7 @@ export class AppMediaViewer {
this.lazyLoadQueue.unshift({
div: null,
load,
wasSeen: true
load
});
});
}

View File

@ -1,4 +1,4 @@
import { $rootScope, copy, tsNow, safeReplaceObject, dT, listMergeSorted, deepEqual, langPack } from "../utils";
import { $rootScope, copy, tsNow, safeReplaceObject, listMergeSorted, deepEqual, langPack } from "../utils";
import appMessagesIDsManager from "./appMessagesIDsManager";
import appChatsManager from "./appChatsManager";
import appUsersManager from "./appUsersManager";
@ -231,7 +231,7 @@ export class FiltersStorage {
public orderIndex = 0;
constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
this.handleUpdate(e.detail);
});
}
@ -476,7 +476,7 @@ export class AppMessagesManager {
public lastSearchFilter: any = {};
public lastSearchResults: any = [];
public needSingleMessages: any = [];
public needSingleMessages: number[] = [];
public fetchSingleMessagesTimeout = 0;
private fetchSingleMessagesPromise: Promise<any> = null;
@ -486,7 +486,7 @@ export class AppMessagesManager {
public migratedToFrom: {[peerID: number]: number} = {};
public newMessagesHandlePromise = 0;
public newMessagesToHandle: any = {};
public newMessagesToHandle: {[peerID: string]: number[]} = {};
public newDialogsHandlePromise = 0;
public newDialogsToHandle: {[peerID: string]: {reload: true} | Dialog} = {};
public newUpdatesAfterReloadToHandle: any = {};
@ -511,11 +511,11 @@ export class AppMessagesManager {
public filtersStorage = new FiltersStorage();
constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
this.handleUpdate(e.detail);
});
$rootScope.$on('webpage_updated', (e: CustomEvent) => {
$rootScope.$on('webpage_updated', (e) => {
let eventData = e.detail;
eventData.msgs.forEach((msgID: number) => {
let message = this.getMessage(msgID);
@ -529,7 +529,7 @@ export class AppMessagesManager {
});
});
$rootScope.$on('draft_updated', (e: CustomEvent) => {
/* $rootScope.$on('draft_updated', (e) => {
let eventData = e.detail;;
var peerID = eventData.peerID;
var draft = eventData.draft;
@ -558,12 +558,12 @@ export class AppMessagesManager {
this.dialogsStorage.pushDialog(dialog);
$rootScope.$broadcast('dialog_draft', {
peerID: peerID,
draft: draft,
peerID,
draft,
index: dialog.index
});
}
});
}); */
}
@ -847,7 +847,7 @@ export class AppMessagesManager {
this.saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
$rootScope.$broadcast('history_append', {peerID, messageID, my: true});
setTimeout(() => message.send(), 0);
// setTimeout(function () {
@ -1216,7 +1216,7 @@ export class AppMessagesManager {
this.saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
$rootScope.$broadcast('history_append', {peerID, messageID, my: true});
setTimeout(message.send.bind(this), 0);
@ -1370,7 +1370,7 @@ export class AppMessagesManager {
return message;
});
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messages[messages.length - 1].id, my: true});
$rootScope.$broadcast('history_append', {peerID, messageID: messages[messages.length - 1].id, my: true});
let toggleError = (message: any, on: boolean) => {
if(on) {
@ -1730,7 +1730,7 @@ export class AppMessagesManager {
this.saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
$rootScope.$broadcast('history_append', {peerID, messageID, my: true});
setTimeout(message.send, 0);
@ -1876,20 +1876,25 @@ export class AppMessagesManager {
//flags |= 1; // means pinned already loaded
}
/* if(this.dialogsStorage.dialogsOffsetDate[0]) {
flags |= 1; // means pinned already loaded
} */
//if(folderID > 0) {
//flags |= 1;
flags |= 2;
//}
// ! ВНИМАНИЕ: ОЧЕНЬ СЛОЖНАЯ ЛОГИКА:
// ! если делать запрос сначала по папке 0, потом по папке 1, по индексу 0 в массиве будет один и тот же диалог, при условии что он закреплён в обеих папках, ЛОЛ???
// ! если делать запрос сначала по папке 0, потом по папке 1, по индексу 0 в массиве будет один и тот же диалог, с dialog.pFlags.pinned, ЛОЛ???
// ! т.е., с запросом folder_id: 1, и exclude_pinned: 0, в результате будут ещё и закреплённые с папки 0
return apiManager.invokeApi('messages.getDialogs', {
flags: flags,
flags,
folder_id: folderID,
offset_date: offsetDate,
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
offset_peer: appPeersManager.getInputPeerByID(offsetPeerID),
limit: limit,
limit,
hash: 0
}, {
//timeout: APITIMEOUT,
@ -1897,7 +1902,7 @@ export class AppMessagesManager {
}).then((dialogsResult) => {
if(dialogsResult._ == 'messages.dialogsNotModified') return null;
//this.log.error('messages.getDialogs result:', {...dialogsResult.dialogs[0]});
//this.log.error('messages.getDialogs result:', dialogsResult.dialogs, {...dialogsResult.dialogs[0]});
if(!offsetDate) {
telegramMeWebService.setAuthorized(true);
@ -1909,7 +1914,7 @@ export class AppMessagesManager {
let maxSeenIdIncremented = offsetDate ? true : false;
let hasPrepend = false;
let noIDsDialogs: {[peerID: number]: Dialog} = {};
const noIDsDialogs: {[peerID: number]: Dialog} = {};
(dialogsResult.dialogs as Dialog[]).forEachReverse(dialog => {
//const d = Object.assign({}, dialog);
// ! нужно передавать folderID, так как по папке != 0 нет свойства folder_id
@ -2561,7 +2566,7 @@ export class AppMessagesManager {
$rootScope.$broadcast('dialog_drop', {peerID: migrateFrom, dialog: dropped[0]});
}
$rootScope.$broadcast('dialog_migrate', {migrateFrom: migrateFrom, migrateTo: migrateTo});
$rootScope.$broadcast('dialog_migrate', {migrateFrom, migrateTo});
}, 100);
}
}
@ -2756,7 +2761,7 @@ export class AppMessagesManager {
}
this.historiesStorage[peerID] = historyStorage;
if(this.mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID});
$rootScope.$broadcast('history_reply_markup', {peerID});
}
}
@ -3209,7 +3214,7 @@ export class AppMessagesManager {
apiPromise = apiManager.invokeApi('messages.readHistory', {
peer: appPeersManager.getInputPeerByID(peerID),
max_id: maxID
}).then((affectedMessages: any) => {
}).then((affectedMessages) => {
apiUpdatesManager.processUpdateMessage({
_: 'updateShort',
update: {
@ -3299,7 +3304,7 @@ export class AppMessagesManager {
} else {
apiManager.invokeApi('messages.readMessageContents', {
id: msgIDs
}).then((affectedMessages: any) => {
}).then((affectedMessages) => {
apiUpdatesManager.processUpdateMessage({
_: 'updateShort',
update: {
@ -3385,7 +3390,7 @@ export class AppMessagesManager {
var topMsgID = history[0];
history.unshift(message.mid);
if(message.mid > 0 && message.mid < topMsgID) {
history.sort((a: any, b: any) => {
history.sort((a, b) => {
return b - a;
});
}
@ -3396,7 +3401,7 @@ export class AppMessagesManager {
}
if(this.mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID});
$rootScope.$broadcast('history_reply_markup', {peerID});
}
if(!message.pFlags.out && message.from_id) {
@ -3408,7 +3413,7 @@ export class AppMessagesManager {
if(randomID) {
if(pendingMessage = this.finalizePendingMessage(randomID, message)) {
$rootScope.$broadcast('history_update', {peerID: peerID, mid: message.mid});
$rootScope.$broadcast('history_update', {peerID, mid: message.mid});
}
delete this.pendingByMessageID[message.mid];
@ -3542,11 +3547,11 @@ export class AppMessagesManager {
dialogsResult.dialogs.reverse();
this.applyConversations(dialogsResult);
dialogsResult.dialogs.forEach((dialog: any) => {
dialogsResult.dialogs.forEach((dialog) => {
newPinned[dialog.peerID] = true;
});
this.dialogsStorage.getFolder(folderID).forEach((dialog: any) => {
this.dialogsStorage.getFolder(folderID).forEach((dialog) => {
const peerID = dialog.peerID;
if(dialog.pFlags.pinned && !newPinned[peerID]) {
this.newDialogsToHandle[peerID] = {reload: true};
@ -3626,7 +3631,7 @@ export class AppMessagesManager {
});
if(isTopMessage) {
var updatedDialogs: any = {};
var updatedDialogs: {[peerID: number]: Dialog} = {};
updatedDialogs[peerID] = dialog;
$rootScope.$broadcast('dialogs_multiupdate', updatedDialogs);
}
@ -3889,10 +3894,7 @@ export class AppMessagesManager {
let message = this.getMessage(mid);
if(message && message.views && message.views < views) {
message.views = views;
$rootScope.$broadcast('message_views', {
mid: mid,
views: views
});
$rootScope.$broadcast('message_views', {mid, views});
}
break;
}
@ -3987,7 +3989,7 @@ export class AppMessagesManager {
public finalizePendingMessageCallbacks(tempID: number, mid: number) {
var callbacks = this.tempFinalizeCallbacks[tempID];
this.log.warn(dT(), callbacks, tempID);
this.log.warn(callbacks, tempID);
if(callbacks !== undefined) {
callbacks.forEach((callback: any) => {
callback(mid);
@ -4003,9 +4005,9 @@ export class AppMessagesManager {
return false;
}
AppStorage.set({
max_seen_msg: maxID
});
this.maxSeenID = maxID;
AppStorage.set({max_seen_msg: maxID});
apiManager.invokeApi('messages.receivedMessages', {
max_id: maxID
@ -4149,7 +4151,7 @@ export class AppMessagesManager {
historyStorage.history.splice(offset, historyStorage.history.length - offset);
historyResult.messages.forEach((message: any) => {
if(this.mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID});
$rootScope.$broadcast('history_reply_markup', {peerID});
}
historyStorage.history.push(message.mid);

View File

@ -75,7 +75,7 @@ class AppPollsManager {
private log = logger('POLLS', LogLevels.error);
constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
let update = e.detail;
this.handleUpdate(update);

View File

@ -249,7 +249,7 @@ export class AppSidebarLeft extends SidebarSlider {
});
});
$rootScope.$on('dialogs_archived_unread', (e: CustomEvent) => {
$rootScope.$on('dialogs_archived_unread', (e) => {
this.archivedCount.innerText = '' + e.detail.count;
});

View File

@ -42,7 +42,7 @@ class AppStickersManager {
//}
});
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
const update = e.detail;
switch(update._) {
@ -121,7 +121,7 @@ class AppStickersManager {
//console.log('stickers wrote', this.stickerSets);
if(this.saveSetsTimeout) return;
this.saveSetsTimeout = setTimeout(() => {
this.saveSetsTimeout = window.setTimeout(() => {
const savedSets: {[id: string]: MessagesStickerSet} = {};
for(const id in this.stickerSets) {
const set = this.stickerSets[id];

View File

@ -64,7 +64,7 @@ export class AppUsersManager {
this.myID = id;
});
$rootScope.$on('user_auth', (e: CustomEvent) => {
$rootScope.$on('user_auth', (e) => {
let userAuth = e.detail;
this.myID = userAuth ? userAuth.id : 0;
});
@ -73,7 +73,7 @@ export class AppUsersManager {
$rootScope.$on('stateSynchronized', this.updateUsersStatuses.bind(this));
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
let update = e.detail;
//console.log('on apiUpdate', update);
switch(update._) {

View File

@ -1,4 +1,4 @@
import { $rootScope, safeReplaceObject, copy } from "../utils";
import { $rootScope, safeReplaceObject } from "../utils";
import appPhotosManager from "./appPhotosManager";
import appDocsManager from "./appDocsManager";
import { RichTextProcessor } from "../richtextprocessor";
@ -8,7 +8,7 @@ class AppWebPagesManager {
pendingWebPages: any = {};
constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
$rootScope.$on('apiUpdate', (e) => {
let update = e.detail;
switch(update._) {
@ -91,9 +91,9 @@ class AppWebPagesManager {
}
if(!messageID && this.pendingWebPages[apiWebPage.id] !== undefined) {
var msgs = [];
const msgs: number[] = [];
for(let msgID in this.pendingWebPages[apiWebPage.id]) {
msgs.push(msgID);
msgs.push(+msgID);
}
$rootScope.$broadcast('webpage_updated', {

View File

@ -279,7 +279,7 @@ export class RLottiePlayer {
if(delta < 0) {
if(this.rafId) clearTimeout(this.rafId);
return this.rafId = setTimeout(() => {
return this.rafId = window.setTimeout(() => {
this.renderFrame2(frame, frameNo);
}, this.frInterval > -delta ? -delta % this.frInterval : this.frInterval);
//await new Promise((resolve) => setTimeout(resolve, -delta % this.frInterval));

View File

@ -1,4 +1,7 @@
import { Dialog } from "./appManagers/appMessagesManager";
import type { StickerSet } from "../layer";
import type { MyDocument } from "./appManagers/appDocsManager";
import type { Poll, PollResults } from "./appManagers/appPollsManager";
import type { AppMessagesManager, Dialog, MyDialogFilter } from "./appManagers/appMessagesManager";
/*!
* Webogram v0.7.0 - messaging web application for MTProto
* https://github.com/zhukov/webogram
@ -153,55 +156,58 @@ export function getRichElementValue(node: any, lines: string[], line: string[],
} */
type BroadcastEvents = {
'download_progress': any,
'user_update': any,
'user_auth': any,
'peer_changed': any,
'user_update': number,
'user_auth': {dcID?: number, id: number},
'peer_changed': number,
'filter_delete': any,
'filter_update': any,
'filter_delete': MyDialogFilter,
'filter_update': MyDialogFilter,
'dialog_draft': any,
'dialog_draft': {peerID: number, draft: any, index: number},
'dialog_unread': {peerID: number, count?: number},
'dialog_flush': {peerID: number},
'dialog_drop': {peerID: number, dialog?: Dialog},
'dialog_migrate': any,
'dialog_migrate': {migrateFrom: number, migrateTo: number},
'dialog_top': Dialog,
'dialog_notify_settings': number,
'dialogs_multiupdate': {[peerID: string]: Dialog},
'dialogs_archived_unread': any,
'dialogs_archived_unread': {count: number},
'history_append': any,
'history_update': any,
'history_reply_markup': any,
'history_multiappend': any,
'history_append': {peerID: number, messageID: number, my?: boolean},
'history_update': {peerID: number, mid: number},
'history_reply_markup': {peerID: number},
'history_multiappend': AppMessagesManager['newMessagesToHandle'],
'history_delete': {peerID: number, msgs: {[mid: number]: true}},
'history_forbidden': number,
'history_reload': number,
'history_request': any,
'history_request': void,
'message_edit': any,
'message_views': any,
'message_sent': any,
'message_edit': {peerID: number, id: number, mid: number, justMedia: boolean},
'message_views': {mid: number, views: number},
'message_sent': {tempID: number, mid: number},
'messages_pending': void,
'messages_read': any,
'messages_downloaded': any,
'messages_read': void,
'messages_downloaded': number[],
'stickers_installed': StickerSet.stickerSet,
'stickers_deleted': StickerSet.stickerSet,
'audio_play': {doc: MyDocument, mid: number},
'audio_pause': void,
//'contacts_update': any,
'avatar_update': number,
'chat_full_update': number,
'peer_pinned_message': number,
'poll_update': {poll: Poll, results: PollResults},
'chat_update': number,
'stateSynchronized': void,
'channel_settings': {channelID: number},
'webpage_updated': {id: string, msgs: number[]},
'contacts_update': any,
'avatar_update': any,
'stickers_installed': any,
'stickers_deleted': any,
'chat_full_update': any,
'peer_pinned_message': any,
'poll_update': any,
'audio_play': any,
'audio_pause': any,
'chat_update': any,
'apiUpdate': any,
'stateSynchronized': any,
'channel_settings': any,
'webpage_updated': any,
'draft_updated': any,
'download_progress': any,
//'draft_updated': any,
};
export const $rootScope = {