From 728c4932ae9a0a7353bf4f9965b2f43edcca4ace Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Wed, 18 Aug 2021 17:48:13 +0300 Subject: [PATCH] Open documents in media viewer --- src/components/appMediaViewer.ts | 91 ++++++++++++++--------- src/components/audio.ts | 1 + src/components/chat/bubbles.ts | 81 +++++++++++++------- src/components/chat/contextMenu.ts | 7 +- src/components/wrappers.ts | 22 +++++- src/lib/appManagers/appDocsManager.ts | 10 ++- src/lib/appManagers/appMessagesManager.ts | 14 ++++ src/lib/appManagers/appPhotosManager.ts | 35 ++++++--- src/lib/rootScope.ts | 28 +++---- 9 files changed, 197 insertions(+), 92 deletions(-) diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index f98e2fa3..32c64282 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -11,7 +11,7 @@ import { isMobileSafari, isSafari } from "../helpers/userAgent"; import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager"; import appImManager from "../lib/appManagers/appImManager"; import appMessagesManager from "../lib/appManagers/appMessagesManager"; -import appPhotosManager from "../lib/appManagers/appPhotosManager"; +import appPhotosManager, { MyPhoto } from "../lib/appManagers/appPhotosManager"; import { logger } from "../lib/logger"; import VideoPlayer from "../lib/mediaPlayer"; import { RichTextProcessor } from "../lib/richtextprocessor"; @@ -36,7 +36,7 @@ import { Message } from "../layer"; import { forEachReverse } from "../helpers/array"; import AppSharedMediaTab from "./sidebarRight/tabs/sharedMedia"; import findUpClassName from "../helpers/dom/findUpClassName"; -import renderImageFromUrl from "../helpers/dom/renderImageFromUrl"; +import renderImageFromUrl, { renderImageFromUrlPromise } from "../helpers/dom/renderImageFromUrl"; import getVisibleRect from "../helpers/dom/getVisibleRect"; import appDownloadManager from "../lib/appManagers/appDownloadManager"; import { cancelEvent } from "../helpers/dom/cancelEvent"; @@ -48,6 +48,7 @@ import appMessagesIdsManager from "../lib/appManagers/appMessagesIdsManager"; import I18n, { i18n } from "../lib/langPack"; import { capitalizeFirstLetter } from "../helpers/string"; import setInnerHTML from "../helpers/dom/setInnerHTML"; +import { doubleRaf, fastRaf } from "../helpers/schedulers"; // TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию // TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода) @@ -511,8 +512,15 @@ class AppMediaViewerBase(); const ret = {onAnimationEnd: deferred}; - this.setMoverAnimationPromise.then(() => { + const timeout = setTimeout(() => { + if(!deferred.isFulfilled && !deferred.isRejected) { + deferred.resolve(); + } + }, 1000); + + this.setMoverAnimationPromise.finally(() => { this.setMoverAnimationPromise = null; + clearTimeout(timeout); }); if(!closing) { @@ -520,9 +528,11 @@ class AppMediaViewerBase { - mediaElement.addEventListener('load', resolve); - - if(src) { - mediaElement.src = src; - } - }); + await renderImageFromUrlPromise(mediaElement, src); } }/* else if(mediaElement instanceof HTMLVideoElement && mediaElement.firstElementChild && ((mediaElement.firstElementChild as HTMLSourceElement).src || src)) { await new Promise((resolve, reject) => { @@ -625,7 +629,7 @@ class AppMediaViewerBase { + fastRaf(() => { mover.classList.add(wasActive ? 'moving' : 'active'); }); } else { @@ -674,7 +678,7 @@ class AppMediaViewerBase setTimeout(resolve, 0)); //await new Promise((resolve) => window.requestAnimationFrame(resolve)); // * одного RAF'а недостаточно, иногда анимация с одним не срабатывает (преимущественно на мобильных) - await new Promise((resolve) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve))); + await doubleRaf(); // чтобы проверить установленную позицию - раскомментировать // throw ''; @@ -779,7 +783,7 @@ class AppMediaViewerBase = Promise.resolve(); - const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true).photoSize; + const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true, undefined, media._ === 'document' && media.w && media.h).photoSize; if(useContainerAsTarget) { const cacheContext = appDownloadManager.getCacheContext(media, size.type); let img: HTMLImageElement; @@ -1040,7 +1046,8 @@ class AppMediaViewerBase; if(isVideo) { @@ -1072,6 +1079,16 @@ class AppMediaViewerBase { + if(video.error.code !== 4) { + this.log.error("Error " + video.error.code + "; details: " + video.error.message); + } + + if(preloader) { + preloader.detach(); + } + }, {once: true}); if(isSafari) { // test stream @@ -1107,7 +1124,7 @@ class AppMediaViewerBase { this.wholeDiv.classList.toggle('has-video-controls', show); }); @@ -1118,7 +1135,7 @@ class AppMediaViewerBase { if(video.readyState < video.HAVE_FUTURE_DATA) { preloader.attach(mover, true); @@ -1158,9 +1175,9 @@ class AppMediaViewerBase { const cacheContext = appDownloadManager.getCacheContext(media); - const promise = media.supportsStreaming ? Promise.resolve() : appDocsManager.downloadDoc(media); + const promise: Promise = supportsStreaming ? Promise.resolve() : appDocsManager.downloadDoc(media); - if(!media.supportsStreaming) { + if(!supportsStreaming) { onAnimationEnd.then(() => { if(!cacheContext.url) { preloader.attach(mover, true, promise); @@ -1168,7 +1185,7 @@ class AppMediaViewerBase).then(async() => { + Promise.all([promise, onAnimationEnd]).then(async() => { if(this.tempId !== tempId) { this.log.warn('media viewer changed video'); return; @@ -1204,7 +1221,7 @@ class AppMediaViewerBase { const cacheContext = appDownloadManager.getCacheContext(media, size.type); - const cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); + const cancellablePromise = isDocument ? appDocsManager.downloadDoc(media) : appPhotosManager.preloadPhoto(media, size); onAnimationEnd.then(() => { if(!cacheContext.url) { @@ -1247,7 +1264,7 @@ class AppMediaViewerBase { + fastRaf(() => { haveImage.remove(); }); } @@ -1477,12 +1494,16 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet } const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history); + const isForDocument = this.searchContext.inputFilter === 'inputMessagesFilterDocument'; method((message: Message.message) => { const {mid, peerId} = message; - const media = this.getMediaFromMessage(message); + const media: MyPhoto | MyDocument = appMessagesManager.getMediaFromMessage(message); if(!media) return; - //if(media._ === 'document' && media.type !== 'video') return; + + if(isForDocument && !AppMediaViewer.isMediaCompatibleForDocumentViewer(media)) { + return; + } const t = {element: null as HTMLElement, mid, peerId}; if(older) { @@ -1507,12 +1528,6 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet return promise; }; - private getMediaFromMessage(message: any) { - return message.action ? message.action.photo : message.media.photo - || message.media.document - || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)); - } - private setCaption(message: Message.message) { const caption = message.message; let html = ''; @@ -1548,7 +1563,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet const mid = message.mid; const fromId = message.fromId; - const media = this.getMediaFromMessage(message); + const media = appMessagesManager.getMediaFromMessage(message); this.buttons.forward.classList.toggle('hide', message._ === 'messageService'); @@ -1559,6 +1574,10 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet return promise; } + + public static isMediaCompatibleForDocumentViewer(media: MyPhoto | MyDocument) { + return media._ === 'photo' || (['photo', 'video', 'gif'].includes(media.type) || media.mime_type.indexOf('video/') === 0); + } } type AppMediaViewerAvatarTargetType = {element: HTMLElement, photoId: string}; diff --git a/src/components/audio.ts b/src/components/audio.ts index 378530b4..d2dd5ed5 100644 --- a/src/components/audio.ts +++ b/src/components/audio.ts @@ -216,6 +216,7 @@ function wrapVoiceMessage(audioEl: AudioElement) { }); progress.addEventListener('mousedown', (e) => { e.preventDefault(); + if(e.button !== 1) return; if(!audio.paused) { audio.pause(); } diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 4097aecd..a2bf01a9 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -955,50 +955,75 @@ export default class ChatBubbles { return; } + const documentDiv = findUpClassName(target, 'document-with-thumb'); if((target.tagName === 'IMG' && !target.classList.contains('emoji') && !target.classList.contains('document-thumb')) || target.classList.contains('album-item') || isVideoComponentElement - || (target.tagName === 'VIDEO' && !bubble.classList.contains('round'))) { - let messageId = +findUpClassName(target, 'album-item')?.dataset.mid || +bubble.dataset.mid; - let message = this.chat.getMessage(messageId); + || (target.tagName === 'VIDEO' && !bubble.classList.contains('round')) + || (documentDiv && !documentDiv.querySelector('.preloader-container'))) { + const groupedItem = findUpClassName(target, 'album-item') || findUpClassName(target, 'document-container'); + const messageId = +(groupedItem || bubble).dataset.mid; + const message = this.chat.getMessage(messageId); if(!message) { this.log.warn('no message by messageId:', messageId); return; } - let targets: {element: HTMLElement, mid: number, peerId: number}[] = []; - let ids = Object.keys(this.bubbles).map(k => +k).filter(id => { + const f = documentDiv ? (media: any) => { + return AppMediaViewer.isMediaCompatibleForDocumentViewer(media); + } : (media: any) => { + return media._ === 'photo' || ['video', 'gif'].includes(media.type); + }; + + const targets: {element: HTMLElement, mid: number, peerId: number}[] = []; + const ids = Object.keys(this.bubbles).map(k => +k).filter(id => { //if(!this.scrollable.visibleElements.find(e => e.element === this.bubbles[id])) return false; - let message = this.chat.getMessage(id); + const message = this.chat.getMessage(id); + const media = this.appMessagesManager.getMediaFromMessage(message); - return message.media && (message.media.photo || (message.media.document && (message.media.document.type === 'video' || message.media.document.type === 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo))); + return media && f(media); }).sort((a, b) => a - b); ids.forEach(id => { - let withTail = this.bubbles[id].classList.contains('with-media-tail'); - let str = '.album-item video, .album-item img, .preview video, .preview img, '; - if(withTail) { - str += '.bubble__media-container'; + let selector: string; + if(documentDiv) { + selector = '.document-container'; } else { - str += '.attachment video, .attachment img'; + const withTail = this.bubbles[id].classList.contains('with-media-tail'); + selector = '.album-item video, .album-item img, .preview video, .preview img, '; + if(withTail) { + selector += '.bubble__media-container'; + } else { + selector += '.attachment video, .attachment img'; + } } - const hasAspecter = !!this.bubbles[id].querySelector('.media-container-aspecter'); - let elements = this.bubbles[id].querySelectorAll(str) as NodeListOf; + const elements = Array.from(this.bubbles[id].querySelectorAll(selector)) as HTMLElement[]; const parents: Set = new Set(); - Array.from(elements).forEach((element: HTMLElement) => { - if(hasAspecter && !findUpClassName(element, 'media-container-aspecter')) return; - let albumItem = findUpClassName(element, 'album-item'); - const parent = albumItem || element.parentElement; - if(parents.has(parent)) return; - parents.add(parent); - targets.push({ - element, - mid: +albumItem?.dataset.mid || id, - peerId: this.peerId + if(documentDiv) { + elements.forEach((element) => { + targets.push({ + element: element.querySelector('.document-ico'), + mid: +element.dataset.mid, + peerId: this.peerId + }); }); - }); + } else { + const hasAspecter = !!this.bubbles[id].querySelector('.media-container-aspecter'); + elements.forEach((element) => { + if(hasAspecter && !findUpClassName(element, 'media-container-aspecter')) return; + let albumItem = findUpClassName(element, 'album-item'); + const parent = albumItem || element.parentElement; + if(parents.has(parent)) return; + parents.add(parent); + targets.push({ + element, + mid: albumItem ? +albumItem.dataset.mid : id, + peerId: this.peerId + }); + }); + } }); targets.sort((a, b) => a.mid - b.mid); @@ -1018,7 +1043,7 @@ export default class ChatBubbles { .setSearchContext({ threadId: this.chat.threadId, peerId: this.peerId, - inputFilter: 'inputMessagesFilterPhotoVideo' + inputFilter: documentDiv ? 'inputMessagesFilterDocument' : 'inputMessagesFilterPhotoVideo' }) .openMedia(message, targets[idx].element, 0, true, targets.slice(0, idx), targets.slice(idx + 1)); @@ -2760,7 +2785,7 @@ export default class ChatBubbles { `; const avatarElem = new AvatarElement(); - //avatarElem.lazyLoadQueue = this.lazyLoadQueue; + avatarElem.lazyLoadQueue = this.lazyLoadQueue; avatarElem.setAttribute('peer', '' + message.media.user_id); avatarElem.classList.add('contact-avatar', 'avatar-54'); @@ -2901,7 +2926,7 @@ export default class ChatBubbles { const needAvatar = this.chat.isAnyGroup() && !isOut; if(needAvatar) { let avatarElem = new AvatarElement(); - //avatarElem.lazyLoadQueue = this.lazyLoadQueue; + avatarElem.lazyLoadQueue = this.lazyLoadQueue; avatarElem.classList.add('user-avatar', 'avatar-40'); avatarElem.loadPromises = loadPromises; diff --git a/src/components/chat/contextMenu.ts b/src/components/chat/contextMenu.ts index 6adf8b8f..c12a0ee3 100644 --- a/src/components/chat/contextMenu.ts +++ b/src/components/chat/contextMenu.ts @@ -283,7 +283,12 @@ export default class ChatContextMenu { } const doc: MyDocument = this.message.media?.document; - return doc && doc.type && !(['gif', 'photo', 'video', 'sticker'] as MyDocument['type'][]).includes(doc.type); + if(!doc) return false; + + let hasTarget = !!isTouchSupported; + const isGoodType = !doc.type || !(['gif', 'video', 'sticker'] as MyDocument['type'][]).includes(doc.type); + if(isGoodType) hasTarget = hasTarget || !!findUpClassName(this.target, 'document') || !!findUpClassName(this.target, 'audio'); + return isGoodType && hasTarget; } }, { icon: 'checkretract', diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index f6dd4401..55698344 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -446,6 +446,15 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2); }; +rootScope.addEventListener('download_start', (docId) => { + const elements = Array.from(document.querySelectorAll(`.document[data-doc-id="${docId}"]`)) as HTMLElement[]; + elements.forEach(element => { + if(element.querySelector('.preloader-container.manual')) { + element.click(); + } + }); +}); + export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, noAutoDownload, lazyLoadQueue}: { message: any, withTime?: boolean, @@ -569,14 +578,17 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS const load = () => { const doc = appDocsManager.getDoc(docDiv.dataset.docId); let download: DownloadBlob; + const queueId = appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : undefined; if(doc.type === 'pdf') { - download = appDocsManager.downloadDoc(doc, appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : 0); + download = appDocsManager.downloadDoc(doc, queueId); download.then(() => { const cacheContext = appDownloadManager.getCacheContext(doc); window.open(cacheContext.url); }); + } else if(doc.type === 'photo' || doc.type === 'video' || doc.mime_type.indexOf('video/') === 0) { + download = appDocsManager.downloadDoc(doc, queueId); } else { - download = appDocsManager.saveDocFile(doc, appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : 0); + download = appDocsManager.saveDocFile(doc, queueId); } if(downloadDiv) { @@ -587,7 +599,11 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS return {download}; }; - if(!(cacheContext.downloaded && !uploading)) { + if(appDocsManager.downloading.has(doc.id)) { + downloadDiv = docDiv.querySelector('.document-download'); + preloader = new ProgressivePreloader(); + preloader.attach(downloadDiv, false, appDocsManager.downloading.get(doc.id)); + } else if(!(cacheContext.downloaded && !uploading)) { downloadDiv = docDiv.querySelector('.document-download'); preloader = message.media.preloader as ProgressivePreloader; diff --git a/src/lib/appManagers/appDocsManager.ts b/src/lib/appManagers/appDocsManager.ts index 0aab4d16..55fd5ac2 100644 --- a/src/lib/appManagers/appDocsManager.ts +++ b/src/lib/appManagers/appDocsManager.ts @@ -22,6 +22,7 @@ import blur from '../../helpers/blur'; import apiManager from '../mtproto/mtprotoworker'; import { MOUNT_CLASS_TO } from '../../config/debug'; import { getFullDate } from '../../helpers/date'; +import rootScope from '../rootScope'; export type MyDocument = Document.document; @@ -30,6 +31,7 @@ export type MyDocument = Document.document; export class AppDocsManager { private docs: {[docId: string]: MyDocument} = {}; private savingLottiePreview: {[docId: string]: true} = {}; + public downloading: Map = new Map(); constructor() { apiManager.onServiceWorkerFail = this.onServiceWorkerFail; @@ -187,7 +189,7 @@ export class AppDocsManager { } if(apiManager.isServiceWorkerOnline()) { - if((doc.type === 'gif' && doc.size > 8e6) || doc.type === 'audio' || doc.type === 'video') { + if((doc.type === 'gif' && doc.size > 8e6) || doc.type === 'audio' || doc.type === 'video'/* || doc.mime_type.indexOf('video/') === 0 */) { doc.supportsStreaming = true; const cacheContext = appDownloadManager.getCacheContext(doc); @@ -323,13 +325,17 @@ export class AppDocsManager { const downloadOptions = this.getFileDownloadOptions(doc, undefined, queueId, onlyCache); download = appDownloadManager.download(downloadOptions); + this.downloading.set(doc.id, download); + rootScope.dispatchEvent('download_start', doc.id); const cacheContext = appDownloadManager.getCacheContext(doc); const originalPromise = download; originalPromise.then((blob) => { cacheContext.url = URL.createObjectURL(blob); cacheContext.downloaded = blob.size; - }, () => {}); + }, () => {}).finally(() => { + this.downloading.delete(doc.id); + }); if(doc.type === 'voice' && !opusDecodeController.isPlaySupported()) { download = originalPromise.then(async(blob) => { diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 21526925..8e189c72 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -5219,6 +5219,20 @@ export class AppMessagesManager { appWebPagesManager.deleteWebPageFromPending(oldMessage.media.webpage, oldMessage.mid); } } + + public getMediaFromMessage(message: any) { + return message.action ? + message.action.photo : + message.media && ( + message.media.photo || + message.media.document || ( + message.media.webpage && ( + message.media.webpage.document || + message.media.webpage.photo + ) + ) + ); + } } const appMessagesManager = new AppMessagesManager(); diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index 9ccb4806..ce06ef74 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -87,7 +87,7 @@ export class AppPhotosManager { return this.photos[photo.id] = photo; } - public choosePhotoSize(photo: MyPhoto | MyDocument, boxWidth = 0, boxHeight = 0, useBytes = false) { + public choosePhotoSize(photo: MyPhoto | MyDocument, boxWidth = 0, boxHeight = 0, useBytes = false, pushDocumentSize = false) { if(window.devicePixelRatio > 1) { boxWidth *= 2; boxHeight *= 2; @@ -105,7 +105,17 @@ export class AppPhotosManager { d crop 1280x1280 */ let bestPhotoSize: PhotoSize = {_: 'photoSizeEmpty', type: ''}; - const sizes = ((photo as MyPhoto).sizes || (photo as MyDocument).thumbs) as PhotoSize[]; + let sizes = (photo as MyPhoto).sizes || (photo as MyDocument).thumbs as PhotoSize[]; + if(pushDocumentSize && sizes && photo._ === 'document') { + sizes = sizes.concat({ + _: 'photoSize', + w: (photo as MyDocument).w, + h: (photo as MyDocument).h, + size: (photo as MyDocument).size, + type: undefined + }); + } + if(sizes?.length) { for(let i = 0, length = sizes.length; i < length; ++i) { const photoSize = sizes[i]; @@ -214,15 +224,22 @@ export class AppPhotosManager { return {image, loadPromise}; } - public setAttachmentSize(photo: MyPhoto | MyDocument, element: HTMLElement | SVGForeignObjectElement, boxWidth: number, boxHeight: number, noZoom = true, message?: any) { - const photoSize = this.choosePhotoSize(photo, boxWidth, boxHeight); + public setAttachmentSize(photo: MyPhoto | MyDocument, + element: HTMLElement | SVGForeignObjectElement, + boxWidth: number, + boxHeight: number, + noZoom = true, + message?: any, + pushDocumentSize?: boolean) { + const photoSize = this.choosePhotoSize(photo, boxWidth, boxHeight, undefined, pushDocumentSize); //console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div); let size: MediaSize; - if(photo._ === 'document') { - size = makeMediaSize(photo.w || 512, photo.h || 512); + const isDocument = photo._ === 'document'; + if(isDocument) { + size = makeMediaSize((photo as MyDocument).w || (photoSize as PhotoSize.photoSize).w || 512, (photo as MyDocument).h || (photoSize as PhotoSize.photoSize).h || 512); } else { - size = makeMediaSize('w' in photoSize ? photoSize.w : 100, 'h' in photoSize ? photoSize.h : 100); + size = makeMediaSize((photoSize as PhotoSize.photoSize).w || 100, (photoSize as PhotoSize.photoSize).h || 100); } let boxSize = makeMediaSize(boxWidth, boxHeight); @@ -231,7 +248,7 @@ export class AppPhotosManager { let isFit = true; - if(photo._ === 'photo' || ['video', 'gif'].includes(photo.type)) { + if(!isDocument || ['video', 'gif'].includes((photo as MyDocument).type)) { if(boxSize.width < 200 && boxSize.height < 200) { // make at least one side this big boxSize = size = size.aspectCovered(makeMediaSize(200, 200)); } @@ -249,7 +266,7 @@ export class AppPhotosManager { } } - if(isFit && boxSize.width < 120) { // if image is too narrow + if(isFit && boxSize.width < 120 && message) { // if image is too narrow boxSize = makeMediaSize(120, boxSize.height); isFit = false; } diff --git a/src/lib/rootScope.ts b/src/lib/rootScope.ts index 4fd115b2..ca7f0b78 100644 --- a/src/lib/rootScope.ts +++ b/src/lib/rootScope.ts @@ -90,41 +90,43 @@ export type BroadcastEvents = { //'channel_settings': {channelId: number}, 'webpage_updated': {id: string, msgs: {peerId: number, mid: number, isScheduled: boolean}[]}, - 'download_progress': any, 'connection_status_change': ConnectionStatusChange, 'settings_updated': {key: string, value: any}, 'draft_updated': {peerId: number, threadId: number, draft: MyDraftMessage | undefined, force?: boolean}, - + 'event-heavy-animation-start': void, 'event-heavy-animation-end': void, - + 'im_mount': void, 'im_tab_change': number, - + 'idle': boolean, - + 'overlay_toggle': boolean, - + 'background_change': void, - + 'privacy_update': Update.updatePrivacy, - + 'notify_settings': Update.updateNotifySettings, 'notify_peer_type_settings': {key: Exclude, settings: PeerNotifySettings}, - + 'language_change': string, 'theme_change': void, - + 'instance_activated': void, 'instance_deactivated': void, - + 'push_notification_click': PushNotificationObject, 'push_init': PushSubscriptionNotify, 'push_subscribe': PushSubscriptionNotify, 'push_unsubscribe': PushSubscriptionNotify, - - 'emoji_recent': string + + 'emoji_recent': string, + + 'download_start': string, + 'download_progress': any, }; export class RootScope extends EventListenerBase<{