diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index a9b357a3..cc9c79ca 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -447,7 +447,7 @@ class AppMediaViewerBase { - preloader.attach(mover, true, promise); + if(!media.url) { + preloader.attach(mover, true, promise); + } }); } @@ -1056,11 +1058,15 @@ class AppMediaViewerBase { const cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); + onAnimationEnd.then(() => { - this.preloader.attach(mover, true, cancellablePromise); + if(!media.url) { + this.preloader.attach(mover, true, cancellablePromise); + } }); - cancellablePromise.then(() => { - if(this.tempId != tempId) { + + Promise.all([onAnimationEnd, cancellablePromise]).then(() => { + if(this.tempId !== tempId) { this.log.warn('media viewer changed photo'); return; } @@ -1082,16 +1088,13 @@ class AppMediaViewerBase { - if(mediaSizes.isMobile) { - image.classList.remove('thumbnail'); // может здесь это вообще не нужно + if(div.firstElementChild?.tagName === 'IMG') { + div.firstElementChild.remove(); } div.append(image); diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 41b887ef..e116bf59 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -750,6 +750,8 @@ export default class AppSearchSuper { if(testScroll/* || 1 == 1 */) { return; } + + //return; const peerId = this.searchContext.peerId; this.log('load', single, peerId, this.loadPromises); diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 7c9f4e89..fa7d8721 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -43,6 +43,7 @@ import { FocusDirection } from "../../helpers/fastSmoothScroll"; import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent } from "../../hooks/useHeavyAnimationCheck"; import { fastRaf } from "../../helpers/schedulers"; import { deferredPromise, CancellablePromise } from "../../helpers/cancellablePromise"; +import EventListenerBase from "../../helpers/eventListenerBase"; const USE_MEDIA_TAILS = false; const IGNORE_ACTIONS = ['messageActionHistoryClear']; @@ -96,6 +97,7 @@ export default class ChatBubbles { public messagesQueuePromise: Promise = null; private messagesQueue: {message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise[]}[] = []; private messagesQueueOnRender: () => void = null; + private messagesQueueOnRenderAdditional: () => void = null; private firstUnreadBubble: HTMLDivElement = null; private attachedUnreadBubble: boolean; @@ -366,7 +368,7 @@ export default class ChatBubbles { }); } - /* if(false) */this.stickyIntersector = new StickyIntersector(this.scrollable.container, (stuck, target) => { + if(false) this.stickyIntersector = new StickyIntersector(this.scrollable.container, (stuck, target) => { for(const timestamp in this.dateMessages) { const dateMessage = this.dateMessages[timestamp]; if(dateMessage.container === target) { @@ -1467,6 +1469,10 @@ export default class ChatBubbles { this.messagesQueueOnRender(); } + if(this.messagesQueueOnRenderAdditional) { + this.messagesQueueOnRenderAdditional(); + } + queue.forEach(({message, bubble, reverse}) => { this.setBubblePosition(bubble, message, reverse); }); @@ -1595,9 +1601,9 @@ export default class ChatBubbles { contentWrapper.innerHTML = ''; contentWrapper.appendChild(bubbleContainer); //bubbleContainer.style.marginBottom = ''; - const animationDelay = contentWrapper.style.animationDelay; + const transitionDelay = contentWrapper.style.transitionDelay; contentWrapper.style.cssText = ''; - contentWrapper.style.animationDelay = animationDelay; + contentWrapper.style.transitionDelay = transitionDelay; if(bubble === this.firstUnreadBubble) { bubble.classList.add('is-first-unread'); @@ -2636,9 +2642,9 @@ export default class ChatBubbles { const waitPromise = isAdditionRender ? processPromise(resultPromise) : promise; - if(isFirstMessageRender/* && false */) { - waitPromise.then(() => { - if(rootScope.settings.animationsEnabled && Object.keys(this.bubbles).length) { + if(isFirstMessageRender && rootScope.settings.animationsEnabled/* && false */) { + this.messagesQueueOnRenderAdditional = () => { + if(Object.keys(this.bubbles).length > 1) { let sortedMids = getObjectKeysAndSort(this.bubbles, 'desc'); if(isAdditionRender && additionMsgIds.length) { @@ -2664,6 +2670,8 @@ export default class ChatBubbles { topIds.map(m => this.appMessagesManager.getLocalMessageId(m)), bottomIds.map(m => this.appMessagesManager.getLocalMessageId(m))); + const setBubbles: HTMLElement[] = []; + const delay = isAdditionRender ? 10 : 40; const offsetIndex = isAdditionRender ? 0 : 1; const animateAsLadder = (mids: number[], offsetIndex = 0) => { @@ -2678,22 +2686,42 @@ export default class ChatBubbles { const contentWrapper = this.bubbles[mid].lastElementChild as HTMLElement; lastMsDelay = ((idx + offsetIndex) || 0.1) * delay; + //lastMsDelay = (idx + offsetIndex) * delay; //lastMsDelay = (idx || 0.1) * 1000; //if(idx || isSafari) { // ! 0.1 = 1ms задержка для Safari, без этого первое сообщение над самым нижним может появиться позже другого с animation-delay, LOL ! - contentWrapper.style.animationDelay = lastMsDelay + 'ms'; - //} - + //contentWrapper.style.animationDelay = lastMsDelay + 'ms'; + //} + contentWrapper.classList.add('zoom-fade'); - contentWrapper.addEventListener('animationend', () => { - contentWrapper.style.animationDelay = ''; - contentWrapper.classList.remove('zoom-fade'); + contentWrapper.style.transitionDelay = lastMsDelay + 'ms'; + + if(idx === (mids.length - 1)) { + const onTransitionEnd = (e: TransitionEvent) => { + if(e.target !== contentWrapper) { + return; + } + + //contentWrapper.style.animationDelay = ''; + //contentWrapper.classList.remove('zoom-fade'); - if(idx === (mids.length - 1)) { + //this.log('onTransitionEnd', e); + animationPromise.resolve(); - } - }, {once: true}); + + contentWrapper.removeEventListener('transitionend', onTransitionEnd); + }; + + contentWrapper.addEventListener('transitionend', onTransitionEnd); + } + //this.log('supa', bubble); + + setBubbles.push(contentWrapper); + + fastRaf(() => { + contentWrapper.classList.remove('zoom-fade'); + }); }); if(!mids.length) { @@ -2712,6 +2740,13 @@ export default class ChatBubbles { let promise: Promise; if(topIds.length || middleIds.length || bottomIds.length) { promise = Promise.all(promises); + promise.then(() => { + fastRaf(() => { + setBubbles.forEach(contentWrapper => { + contentWrapper.style.transitionDelay = ''; + }); + }); + }); dispatchHeavyAnimationEvent(promise, Math.max(...delays) + 200); // * 200 - transition time } @@ -2721,7 +2756,13 @@ export default class ChatBubbles { }, 0); }); } - }); + + if(!isAdditionRender) { + this.messagesQueueOnRenderAdditional = undefined; + } + }; + } else { + this.messagesQueueOnRenderAdditional = undefined; } (reverse ? this.getHistoryTopPromise = waitPromise : this.getHistoryBottomPromise = waitPromise); @@ -2733,7 +2774,7 @@ export default class ChatBubbles { return null; } - false && !isFirstMessageRender && promise.then(() => { + /* false && */!isFirstMessageRender && promise.then(() => { if(reverse) { this.loadedTopTimes++; this.loadedBottomTimes = Math.max(0, --this.loadedBottomTimes); diff --git a/src/components/chat/chat.ts b/src/components/chat/chat.ts index 890e5451..181addd7 100644 --- a/src/components/chat/chat.ts +++ b/src/components/chat/chat.ts @@ -172,6 +172,7 @@ export default class Chat extends EventListenerBase<{ appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId); this.input.clearHelper(); // костыль + this.selection.cleanup(); // TODO: REFACTOR !!!!!! } this.peerChanged = samePeer; diff --git a/src/components/misc.ts b/src/components/misc.ts index b226ff6a..846fbbad 100644 --- a/src/components/misc.ts +++ b/src/components/misc.ts @@ -5,6 +5,7 @@ import mediaSizes from "../helpers/mediaSizes"; import { isTouchSupported } from "../helpers/touchSupport"; import { isApple } from "../helpers/userAgent"; import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config"; +import { getHeavyAnimationPromise } from "../hooks/useHeavyAnimationCheck"; export const loadedURLs: {[url: string]: boolean} = {}; const set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoElement, url: string) => { @@ -32,7 +33,15 @@ export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGIma loadedURLs[url] = true; //console.log('onload:', url, performance.now() - perf); - callback && callback(); + if(callback) { + // TODO: переделать прогрузки аватаров до начала анимации, иначе с этим ожиданием они неприятно появляются + /* getHeavyAnimationPromise().then(() => { + callback(); + }); */ + callback(); + } + + //callback && callback(); }); if(callback) { diff --git a/src/components/preloader.ts b/src/components/preloader.ts index 8ae41d25..da5657e7 100644 --- a/src/components/preloader.ts +++ b/src/components/preloader.ts @@ -185,6 +185,8 @@ export default class ProgressivePreloader { this.attachPromise(promise); } + //return; + this.detached = false; /* window.requestAnimationFrame(() => { if(this.detached) return; diff --git a/src/components/sidebarLeft/tabs/editProfile.ts b/src/components/sidebarLeft/tabs/editProfile.ts index a4f4be65..c59a5ebd 100644 --- a/src/components/sidebarLeft/tabs/editProfile.ts +++ b/src/components/sidebarLeft/tabs/editProfile.ts @@ -52,7 +52,7 @@ export default class AppEditProfileTab extends SliderSuperTab { this.content.append(this.nextBtn); this.avatarElem = document.createElement('avatar-element') as AvatarElement; - this.avatarElem.classList.add('avatar-placeholder'); + this.avatarElem.classList.add('avatar-placeholder', 'avatar-120'); this.avatarEdit = new AvatarEdit((_upload) => { this.uploadAvatar = _upload; diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index f9d656f2..0cc1cc10 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -617,13 +617,13 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT //resolve(); if(needFadeIn) { - setTimeout(() => { + image.addEventListener('animationend', () => { image.classList.remove('fade-in'); if(thumbImage) { thumbImage.remove(); } - }, 200); + }, {once: true}); } }); }); @@ -850,10 +850,10 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o element.classList.add('fade-out'); } - setTimeout(() => { + animation.canvas.addEventListener('animationend', () => { animation.canvas.classList.remove('fade-in'); cb(); - }, 200); + }, {once: true}); } appDocsManager.saveLottiePreview(doc, animation.canvas, toneIndex); @@ -904,12 +904,12 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o }); if(needFadeIn) { - setTimeout(() => { + image.addEventListener('animationend', () => { image.classList.remove('fade-in'); if(thumbImage) { thumbImage.remove(); } - }, 200); + }, {once: true}); } }); }; diff --git a/src/helpers/heavyQueue.ts b/src/helpers/heavyQueue.ts index 5f599693..64eac93d 100644 --- a/src/helpers/heavyQueue.ts +++ b/src/helpers/heavyQueue.ts @@ -12,6 +12,10 @@ const heavyQueue: HeavyQueue[] = []; let processingQueue = false; export default function pushHeavyTask(queue: HeavyQueue) { + if(!queue.items.length) { + return Promise.resolve([]); + } + queue.promise = deferredPromise(); heavyQueue.push(queue); processHeavyQueue(); @@ -32,7 +36,11 @@ function processHeavyQueue() { } function timedChunk(queue: HeavyQueue) { - if(!queue.items.length) return Promise.resolve([]); + if(!queue.items.length) { + queue.promise.resolve([]); + return Promise.resolve([]); + } + const todo = queue.items.slice(); const results: T[] = []; diff --git a/src/index.hbs b/src/index.hbs index f8e8c96a..5eb1af2c 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -92,7 +92,7 @@ -
+