[Perf] Teact: Postpone rendering and effects during blocking animation (#4928)

This commit is contained in:
Alexander Zinchuk 2024-09-24 14:48:40 +02:00
parent e731712b74
commit 8e5236d102
4 changed files with 38 additions and 3 deletions

View File

@ -13,6 +13,7 @@ import {
SCROLL_MAX_DURATION,
SERVICE_NOTIFICATIONS_USER_ID,
} from '../../../config';
import { cancelScrollBlockingAnimation, isAnimatingScroll } from '../../../util/animateScroll';
import { copyHtmlToClipboard } from '../../../util/clipboard';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { compact, findLast } from '../../../util/iteratees';
@ -489,6 +490,10 @@ addActionHandler('focusMessage', (global, actions, payload): ActionReturnType =>
global = updateFocusDirection(global, direction, tabId);
}
if (isAnimatingScroll()) {
cancelScrollBlockingAnimation();
}
setGlobal(global, { forceOnHeavyAnimation: true });
actions.openThread({

View File

@ -5,18 +5,29 @@ import { requestMeasure } from '../fasterdom/fasterdom';
const AUTO_END_TIMEOUT = 1000;
let counter = 0;
let counterBlocking = 0;
const [getIsAnimating, setIsAnimating] = createSignal(false);
const [getIsBlockingAnimating, setIsBlockingAnimating] = createSignal(false);
export const getIsHeavyAnimating = getIsAnimating;
export { getIsBlockingAnimating };
export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT) {
export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT, isBlocking = false) {
counter++;
if (counter === 1) {
setIsAnimating(true);
}
if (isBlocking) {
counterBlocking++;
if (counterBlocking === 1) {
setIsBlockingAnimating(true);
}
}
const timeout = window.setTimeout(onEnd, duration);
let hasEnded = false;
@ -32,6 +43,14 @@ export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT) {
if (counter === 0) {
setIsAnimating(false);
}
if (isBlocking) {
counterBlocking--;
if (counterBlocking === 0) {
setIsBlockingAnimating(false);
}
}
}
return onEnd;

View File

@ -8,6 +8,7 @@ import safeExec from '../../util/safeExec';
import { throttleWith } from '../../util/schedulers';
import { createSignal, isSignal, type Signal } from '../../util/signals';
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
import { getIsBlockingAnimating } from './heavyAnimation';
export { getIsHeavyAnimating, beginHeavyAnimation, onFullyIdle } from './heavyAnimation';
@ -329,6 +330,11 @@ let areImmediateEffectsCaptured = false;
*/
const runUpdatePassOnRaf = throttleWith(requestMeasure, () => {
if (getIsBlockingAnimating()) {
getIsBlockingAnimating.once(runUpdatePassOnRaf);
return;
}
const runImmediateEffects = captureImmediateEffects();
idsToExcludeFromUpdate = new Set();

View File

@ -127,7 +127,7 @@ function createMutateFunction(
isAnimating = true;
const prevOnHeavyAnimationEnd = onHeavyAnimationEnd;
onHeavyAnimationEnd = beginHeavyAnimation();
onHeavyAnimationEnd = beginHeavyAnimation(undefined, true);
prevOnHeavyAnimationEnd?.();
animateSingle(() => {
@ -142,7 +142,7 @@ function createMutateFunction(
if (!isAnimating) {
currentArgs = undefined;
onHeavyAnimationEnd!();
onHeavyAnimationEnd?.();
onHeavyAnimationEnd = undefined;
}
@ -155,6 +155,11 @@ export function isAnimatingScroll() {
return isAnimating;
}
export function cancelScrollBlockingAnimation() {
onHeavyAnimationEnd!();
onHeavyAnimationEnd = undefined;
}
function calculateScrollFrom(
container: HTMLElement,
scrollTo: number,