useHeavyAnimationCheck: Add workaround for missing end callback (frozen UI bug)

This commit is contained in:
Alexander Zinchuk 2021-12-10 18:33:34 +01:00
parent 560299e129
commit 9c7dc01f86

View File

@ -6,6 +6,9 @@ const ANIMATION_END_EVENT = 'tt-event-heavy-animation-end';
let timeout: number | undefined; let timeout: number | undefined;
let isAnimating = false; let isAnimating = false;
// Make sure to end even if end callback was not called (which was some hardly-reproducible bug)
const AUTO_END_TIMEOUT = 1000;
export default ( export default (
handleAnimationStart: AnyToVoidFunction, handleAnimationStart: AnyToVoidFunction,
handleAnimationEnd: AnyToVoidFunction, handleAnimationEnd: AnyToVoidFunction,
@ -29,7 +32,7 @@ export function isHeavyAnimating() {
return isAnimating; return isAnimating;
} }
export function dispatchHeavyAnimationEvent(duration?: number) { export function dispatchHeavyAnimationEvent(duration = AUTO_END_TIMEOUT) {
if (!isAnimating) { if (!isAnimating) {
isAnimating = true; isAnimating = true;
document.dispatchEvent(new Event(ANIMATION_START_EVENT)); document.dispatchEvent(new Event(ANIMATION_START_EVENT));
@ -40,16 +43,18 @@ export function dispatchHeavyAnimationEvent(duration?: number) {
timeout = undefined; timeout = undefined;
} }
if (duration) { // Race condition may happen if another `dispatchHeavyAnimationEvent` is called before `onEnd`
timeout = window.setTimeout(() => { function onEnd() {
isAnimating = false; if (timeout) {
document.dispatchEvent(new Event(ANIMATION_END_EVENT)); clearTimeout(timeout);
timeout = undefined; timeout = undefined;
}, duration); }
}
return () => {
isAnimating = false; isAnimating = false;
document.dispatchEvent(new Event(ANIMATION_END_EVENT)); document.dispatchEvent(new Event(ANIMATION_END_EVENT));
}; }
timeout = window.setTimeout(onEnd, duration);
return onEnd;
} }