/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ // * Jolly Cobra's useHeavyAnimationCheck.ts, patched import { AnyToVoidFunction } from '../types'; import ListenerSetter from '../helpers/listenerSetter'; import { CancellablePromise, deferredPromise } from '../helpers/cancellablePromise'; import { pause } from '../helpers/schedulers'; import rootScope from '../lib/rootScope'; import DEBUG from '../config/debug'; const ANIMATION_START_EVENT = 'event-heavy-animation-start'; const ANIMATION_END_EVENT = 'event-heavy-animation-end'; let isAnimating = false; let heavyAnimationPromise: CancellablePromise = deferredPromise(); let promisesInQueue = 0; heavyAnimationPromise.resolve(); const log = console.log.bind(console.log, '[HEAVY-ANIMATION]:'); export function dispatchHeavyAnimationEvent(promise: Promise, timeout?: number) { if(!isAnimating) { heavyAnimationPromise = deferredPromise(); rootScope.broadcast(ANIMATION_START_EVENT); isAnimating = true; DEBUG && log('start'); } ++promisesInQueue; DEBUG && log('attach promise, length:', promisesInQueue, timeout); const promises = [ timeout !== undefined ? pause(timeout) : undefined, promise.finally(() => {}) ].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 <= 0) { onHeavyAnimationEnd(); } }); return heavyAnimationPromise; } function onHeavyAnimationEnd() { if(heavyAnimationPromise.isFulfilled) { return; } 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(); } const add = listenerSetter ? listenerSetter.add.bind(listenerSetter, rootScope) : rootScope.addEventListener.bind(rootScope); const remove = listenerSetter ? listenerSetter.removeManual.bind(listenerSetter, rootScope) : rootScope.removeEventListener.bind(rootScope); add(ANIMATION_START_EVENT, handleAnimationStart); add(ANIMATION_END_EVENT, handleAnimationEnd); return () => { remove(ANIMATION_END_EVENT, handleAnimationEnd); remove(ANIMATION_START_EVENT, handleAnimationStart); }; //}, [handleAnimationEnd, handleAnimationStart]); }