Fix freeze on fast chat switch
This commit is contained in:
parent
f8ae31b6ac
commit
080fb56d82
@ -45,7 +45,7 @@ import AudioElement from "../audio";
|
||||
import { Message, MessageEntity, MessageReplyHeader } from "../../layer";
|
||||
import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { FocusDirection } from "../../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent } from "../../hooks/useHeavyAnimationCheck";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
|
||||
import { fastRaf } from "../../helpers/schedulers";
|
||||
import { deferredPromise } from "../../helpers/cancellablePromise";
|
||||
import RepliesElement from "./replies";
|
||||
@ -67,6 +67,7 @@ import reflowScrollableElement from "../../helpers/dom/reflowScrollableElement";
|
||||
import replaceContent from "../../helpers/dom/replaceContent";
|
||||
import setInnerHTML from "../../helpers/dom/setInnerHTML";
|
||||
import whichChild from "../../helpers/dom/whichChild";
|
||||
import { cancelAnimationByKey } from "../../helpers/animation";
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS: Message.messageService['action']['_'][] = [/* 'messageActionHistoryClear' */];
|
||||
@ -1403,6 +1404,12 @@ export default class ChatBubbles {
|
||||
this.scrollable.loadedAll.top = false;
|
||||
this.scrollable.loadedAll.bottom = false;
|
||||
|
||||
// cancel scroll
|
||||
cancelAnimationByKey(this.scrollable.container);
|
||||
|
||||
// do not wait ending of previous scale animation
|
||||
interruptHeavyAnimation();
|
||||
|
||||
if(TEST_SCROLL !== undefined) {
|
||||
TEST_SCROLL = TEST_SCROLL_TIMES;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import _DEBUG from '../config/debug';
|
||||
import fastBlur from '../vendor/fastBlur';
|
||||
import pushHeavyTask from './heavyQueue';
|
||||
import addHeavyTask from './heavyQueue';
|
||||
|
||||
const RADIUS = 2;
|
||||
const ITERATIONS = 2;
|
||||
@ -16,53 +16,67 @@ const DEBUG = _DEBUG && true;
|
||||
function processBlur(dataUri: string, radius: number, iterations: number) {
|
||||
return new Promise<string>((resolve) => {
|
||||
const img = new Image();
|
||||
|
||||
|
||||
const perf = performance.now();
|
||||
if(DEBUG) {
|
||||
console.log('[blur] start');
|
||||
}
|
||||
|
||||
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
|
||||
|
||||
//ctx.filter = 'blur(2px)';
|
||||
ctx.drawImage(img, 0, 0);
|
||||
fastBlur(ctx, 0, 0, canvas.width, canvas.height, radius, iterations);
|
||||
|
||||
//resolve(canvas.toDataURL());
|
||||
canvas.toBlob(blob => {
|
||||
|
||||
resolve(canvas.toDataURL());
|
||||
if(DEBUG) {
|
||||
console.log(`[blur] end, radius: ${radius}, iterations: ${iterations}, time: ${performance.now() - perf}`);
|
||||
}
|
||||
|
||||
/* canvas.toBlob(blob => {
|
||||
resolve(URL.createObjectURL(blob));
|
||||
|
||||
|
||||
if(DEBUG) {
|
||||
console.log(`[blur] end, radius: ${radius}, iterations: ${iterations}, time: ${performance.now() - perf}`);
|
||||
}
|
||||
});
|
||||
}); */
|
||||
};
|
||||
|
||||
|
||||
img.src = dataUri;
|
||||
});
|
||||
}
|
||||
|
||||
const blurPromises: {[dataUri: string]: Promise<string>} = {};
|
||||
const blurPromises: Map<string, Promise<string>> = new Map();
|
||||
const CACHE_SIZE = 1000;
|
||||
|
||||
export default function blur(dataUri: string, radius: number = RADIUS, iterations: number = ITERATIONS) {
|
||||
if(!dataUri) {
|
||||
console.error('no dataUri for blur', dataUri);
|
||||
return Promise.resolve(dataUri);
|
||||
}
|
||||
|
||||
if(blurPromises.size > CACHE_SIZE) {
|
||||
blurPromises.clear();
|
||||
}
|
||||
|
||||
if(blurPromises[dataUri]) return blurPromises[dataUri];
|
||||
return blurPromises[dataUri] = new Promise<string>((resolve) => {
|
||||
if(blurPromises.has(dataUri)) return blurPromises.get(dataUri);
|
||||
const promise = new Promise<string>((resolve) => {
|
||||
//return resolve(dataUri);
|
||||
pushHeavyTask({
|
||||
addHeavyTask({
|
||||
items: [[dataUri, radius, iterations]],
|
||||
context: null,
|
||||
process: processBlur
|
||||
}).then(results => {
|
||||
}, 'unshift').then(results => {
|
||||
resolve(results[0]);
|
||||
});
|
||||
});
|
||||
|
||||
blurPromises.set(dataUri, promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ type HeavyQueue<T> = {
|
||||
const heavyQueue: HeavyQueue<any>[] = [];
|
||||
let processingQueue = false;
|
||||
|
||||
export default function pushHeavyTask<T>(queue: HeavyQueue<T>) {
|
||||
export default function addHeavyTask<T>(queue: HeavyQueue<T>, method: 'push' | 'unshift' = 'push') {
|
||||
if(!queue.items.length) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
queue.promise = deferredPromise<T[]>();
|
||||
heavyQueue.push(queue);
|
||||
heavyQueue[method](queue);
|
||||
processHeavyQueue();
|
||||
|
||||
return queue.promise;
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
// * Jolly Cobra's useHeavyAnimationCheck.ts, patched
|
||||
|
||||
//import { useEffect } from '../lib/teact/teact';
|
||||
import { AnyToVoidFunction } from '../types';
|
||||
import ListenerSetter from '../helpers/listenerSetter';
|
||||
import { CancellablePromise, deferredPromise } from '../helpers/cancellablePromise';
|
||||
@ -18,12 +17,14 @@ const ANIMATION_START_EVENT = 'event-heavy-animation-start';
|
||||
const ANIMATION_END_EVENT = 'event-heavy-animation-end';
|
||||
|
||||
let isAnimating = false;
|
||||
let heavyAnimationPromise: CancellablePromise<void> = Promise.resolve();
|
||||
let heavyAnimationPromise: CancellablePromise<void> = deferredPromise<void>();
|
||||
let promisesInQueue = 0;
|
||||
|
||||
heavyAnimationPromise.resolve();
|
||||
|
||||
const log = console.log.bind(console.log, '[HEAVY-ANIMATION]:');
|
||||
|
||||
export const dispatchHeavyAnimationEvent = (promise: Promise<any>, timeout?: number) => {
|
||||
export function dispatchHeavyAnimationEvent(promise: Promise<any>, timeout?: number) {
|
||||
if(!isAnimating) {
|
||||
heavyAnimationPromise = deferredPromise<void>();
|
||||
rootScope.broadcast(ANIMATION_START_EVENT);
|
||||
@ -40,29 +41,48 @@ export const dispatchHeavyAnimationEvent = (promise: Promise<any>, timeout?: num
|
||||
].filter(Boolean);
|
||||
|
||||
const perf = performance.now();
|
||||
const _heavyAnimationPromise = heavyAnimationPromise;
|
||||
Promise.race(promises).then(() => {
|
||||
if(heavyAnimationPromise !== _heavyAnimationPromise || heavyAnimationPromise.isFulfilled) { // interrupted
|
||||
return;
|
||||
}
|
||||
|
||||
--promisesInQueue;
|
||||
DEBUG && log('promise end, length:', promisesInQueue, performance.now() - perf);
|
||||
if(!promisesInQueue) {
|
||||
isAnimating = false;
|
||||
promisesInQueue = 0;
|
||||
rootScope.broadcast(ANIMATION_END_EVENT);
|
||||
heavyAnimationPromise.resolve();
|
||||
|
||||
DEBUG && log('end');
|
||||
if(promisesInQueue <= 0) {
|
||||
onHeavyAnimationEnd();
|
||||
}
|
||||
});
|
||||
|
||||
return heavyAnimationPromise;
|
||||
};
|
||||
}
|
||||
|
||||
export const getHeavyAnimationPromise = () => heavyAnimationPromise;
|
||||
function onHeavyAnimationEnd() {
|
||||
if(heavyAnimationPromise.isFulfilled) {
|
||||
return;
|
||||
}
|
||||
|
||||
export default (
|
||||
isAnimating = false;
|
||||
promisesInQueue = 0;
|
||||
rootScope.broadcast(ANIMATION_END_EVENT);
|
||||
heavyAnimationPromise.resolve();
|
||||
|
||||
DEBUG && log('end');
|
||||
}
|
||||
|
||||
export function interruptHeavyAnimation() {
|
||||
onHeavyAnimationEnd();
|
||||
}
|
||||
|
||||
export function getHeavyAnimationPromise() {
|
||||
return heavyAnimationPromise;
|
||||
}
|
||||
|
||||
export default function(
|
||||
handleAnimationStart: AnyToVoidFunction,
|
||||
handleAnimationEnd: AnyToVoidFunction,
|
||||
listenerSetter?: ListenerSetter
|
||||
) => {
|
||||
) {
|
||||
//useEffect(() => {
|
||||
if(isAnimating) {
|
||||
handleAnimationStart();
|
||||
@ -78,4 +98,4 @@ export default (
|
||||
remove(ANIMATION_START_EVENT, handleAnimationStart);
|
||||
};
|
||||
//}, [handleAnimationEnd, handleAnimationStart]);
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user