Fixed bubbles animation
Fix saving state on auth pages
This commit is contained in:
parent
5850e1594d
commit
a4e6aef6a9
@ -447,7 +447,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
let mediaElement: HTMLImageElement | HTMLVideoElement;
|
||||
let src: string;
|
||||
|
||||
if(target.tagName == 'DIV' || target.tagName == 'AVATAR-ELEMENT') { // useContainerAsTarget
|
||||
if(target.tagName === 'DIV' || target.tagName === 'AVATAR-ELEMENT') { // useContainerAsTarget
|
||||
if(target.firstElementChild) {
|
||||
mediaElement = new Image();
|
||||
src = (target.firstElementChild as HTMLImageElement).src;
|
||||
@ -1018,7 +1018,9 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
|
||||
if(!media.supportsStreaming) {
|
||||
onAnimationEnd.then(() => {
|
||||
preloader.attach(mover, true, promise);
|
||||
if(!media.url) {
|
||||
preloader.attach(mover, true, promise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1056,11 +1058,15 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
|
||||
const load = () => {
|
||||
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<ContentAdditionType extends string, ButtonsAdditionType
|
||||
}
|
||||
} else {
|
||||
const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover;
|
||||
let image = div.firstElementChild as HTMLImageElement;
|
||||
if(!image || image.tagName != 'IMG') {
|
||||
image = new Image();
|
||||
}
|
||||
let image = new Image();
|
||||
|
||||
//this.log('will renderImageFromUrl:', image, div, target);
|
||||
|
||||
renderImageFromUrl(image, url, () => {
|
||||
if(mediaSizes.isMobile) {
|
||||
image.classList.remove('thumbnail'); // может здесь это вообще не нужно
|
||||
if(div.firstElementChild?.tagName === 'IMG') {
|
||||
div.firstElementChild.remove();
|
||||
}
|
||||
|
||||
div.append(image);
|
||||
|
@ -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);
|
||||
|
@ -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<void> = null;
|
||||
private messagesQueue: {message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise<void>[]}[] = [];
|
||||
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;
|
||||
}
|
||||
|
||||
if(idx === (mids.length - 1)) {
|
||||
//contentWrapper.style.animationDelay = '';
|
||||
//contentWrapper.classList.remove('zoom-fade');
|
||||
|
||||
//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<any>;
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -185,6 +185,8 @@ export default class ProgressivePreloader {
|
||||
this.attachPromise(promise);
|
||||
}
|
||||
|
||||
//return;
|
||||
|
||||
this.detached = false;
|
||||
/* window.requestAnimationFrame(() => {
|
||||
if(this.detached) return;
|
||||
|
@ -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;
|
||||
|
@ -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});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -12,6 +12,10 @@ const heavyQueue: HeavyQueue<any>[] = [];
|
||||
let processingQueue = false;
|
||||
|
||||
export default function pushHeavyTask<T>(queue: HeavyQueue<T>) {
|
||||
if(!queue.items.length) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
queue.promise = deferredPromise<T[]>();
|
||||
heavyQueue.push(queue);
|
||||
processHeavyQueue();
|
||||
@ -32,7 +36,11 @@ function processHeavyQueue() {
|
||||
}
|
||||
|
||||
function timedChunk<T>(queue: HeavyQueue<T>) {
|
||||
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[] = [];
|
||||
|
||||
|
@ -92,7 +92,7 @@
|
||||
<path id="check" fill="none" d="M 4.7071 12.2929 l 5 5 c 0.3905 0.3905 1.0237 0.3905 1.4142 0 l 11 -11" />
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="main-columns" class="tabs-container">
|
||||
<div id="main-columns" class="tabs-container" data-animation="navigation">
|
||||
<div class="chatlist-container sidebar sidebar-left main-column" id="column-left">
|
||||
<div class="sidebar-slider tabs-container">
|
||||
<div class="sidebar-slider-item item-main">
|
||||
|
@ -1504,8 +1504,9 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
|
||||
.bubble-content-wrapper {
|
||||
transition: transform var(--layer-transition);
|
||||
transition: transform var(--layer-transition), opacity var(--layer-transition);
|
||||
transform: scale(1) translateX(0);
|
||||
transform-origin: center;
|
||||
opacity: 1;
|
||||
|
||||
&.zoom-fade /* .bubble-content */ {
|
||||
@ -1513,9 +1514,8 @@ $bubble-margin: .25rem;
|
||||
transform: scale3d(.8, .8, 1);
|
||||
//transform: scale(.8);
|
||||
opacity: 0;
|
||||
transform-origin: center;
|
||||
animation: zoom-opacity-fade-in .2s ease-in-out forwards;
|
||||
animation-delay: 0;
|
||||
//animation: zoom-opacity-fade-in .2s ease-in-out forwards;
|
||||
//animation-delay: 0s;
|
||||
}
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
|
@ -48,7 +48,7 @@ html:not(.is-safari):not(.is-ios) {
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
max-height: 100%;
|
||||
//transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
|
||||
//@include respond-to(not-handhelds) {
|
||||
position: absolute;
|
||||
|
@ -1,5 +1,5 @@
|
||||
.page-password {
|
||||
#password {
|
||||
.input-field-input {
|
||||
padding-right: 2.5rem;
|
||||
max-height: 54px;
|
||||
|
||||
@ -23,13 +23,16 @@
|
||||
position: absolute;
|
||||
right: .25rem;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 1.25rem;
|
||||
color: $placeholder-color;
|
||||
cursor: pointer;
|
||||
transition: .2s;
|
||||
transition: color .2s;
|
||||
padding: .5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
&:before {
|
||||
content: $tgico-eye1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user