[Refactoring] Move beginHeavyAnimation and onFullyIdle to Teact

This commit is contained in:
Alexander Zinchuk 2024-09-19 20:43:18 +02:00
parent 09203ae76e
commit 8b76de86ba
29 changed files with 144 additions and 148 deletions

View File

@ -1,6 +1,7 @@
import type { RefObject } from 'react';
import type { FC } from '../../lib/teact/teact';
import React, {
getIsHeavyAnimating,
memo, useEffect, useRef, useState,
} from '../../lib/teact/teact';
@ -17,7 +18,7 @@ import { IS_ELECTRON } from '../../util/windowEnvironment';
import useColorFilter from '../../hooks/stickers/useColorFilter';
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
import useFlag from '../../hooks/useFlag';
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
import useHeavyAnimation from '../../hooks/useHeavyAnimation';
import useLastCallback from '../../hooks/useLastCallback';
import usePriorityPlaybackCheck, { isPriorityPlaybackActive } from '../../hooks/usePriorityPlaybackCheck';
import useSharedIntersectionObserver from '../../hooks/useSharedIntersectionObserver';
@ -101,8 +102,8 @@ const AnimatedSticker: FC<OwnProps> = ({
// Delay initialization until heavy animation ends
const [
canInitialize, markCanInitialize, unmarkCanInitialize,
] = useFlag(!isHeavyAnimating() || shouldForceOnHeavyAnimation);
useHeavyAnimationCheck(unmarkCanInitialize, markCanInitialize, shouldForceOnHeavyAnimation);
] = useFlag(!getIsHeavyAnimating() || shouldForceOnHeavyAnimation);
useHeavyAnimation(unmarkCanInitialize, markCanInitialize, shouldForceOnHeavyAnimation);
useEffect(() => {
if (shouldForceOnHeavyAnimation) markCanInitialize();
}, [shouldForceOnHeavyAnimation]);
@ -129,7 +130,7 @@ const AnimatedSticker: FC<OwnProps> = ({
|| isUnmountedRef.current
|| !tgsUrl
|| (sharedCanvas && (!sharedCanvasCoords || !sharedCanvas.offsetWidth || !sharedCanvas.offsetHeight))
|| (isHeavyAnimating() && !shouldForceOnHeavyAnimation)
|| (getIsHeavyAnimating() && !shouldForceOnHeavyAnimation)
) {
return;
}
@ -252,7 +253,7 @@ const AnimatedSticker: FC<OwnProps> = ({
}
}, [playAnimation, animation, tgsUrl]);
useHeavyAnimationCheck(pauseAnimation, playAnimation, !playKey || shouldForceOnHeavyAnimation);
useHeavyAnimation(pauseAnimation, playAnimation, !playKey || shouldForceOnHeavyAnimation);
usePriorityPlaybackCheck(pauseAnimation, playAnimation, !playKey || forceAlways);
// Pausing frame may not happen in background,
// so we need to make sure it happens right after focusing,
@ -282,5 +283,5 @@ export default memo(AnimatedSticker);
function isFrozen(forceAlways = false, forceOnHeavyAnimation = false) {
if (forceAlways) return false;
return (!forceOnHeavyAnimation && isHeavyAnimating()) || isPriorityPlaybackActive() || isBackgroundModeActive();
return (!forceOnHeavyAnimation && getIsHeavyAnimating()) || isPriorityPlaybackActive() || isBackgroundModeActive();
}

View File

@ -9,7 +9,7 @@ import { preloadImage } from '../../../util/files';
import { REM } from '../helpers/mediaDimensions';
import useDynamicColorListener from '../../../hooks/stickers/useDynamicColorListener';
import { useThrottleForHeavyAnimation } from '../../../hooks/useHeavyAnimationCheck';
import { useThrottleForHeavyAnimation } from '../../../hooks/useHeavyAnimation';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang';

View File

@ -1,5 +1,6 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
beginHeavyAnimation,
memo, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
@ -22,7 +23,6 @@ import { waitForTransitionEnd } from '../../../util/cssAnimationEndListeners';
import { IS_TOUCH_ENV } from '../../../util/windowEnvironment';
import useAppLayout from '../../../hooks/useAppLayout';
import { dispatchHeavyAnimationEvent } from '../../../hooks/useHeavyAnimationCheck';
import useHistoryBack from '../../../hooks/useHistoryBack';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver';
@ -148,8 +148,8 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
requestNextMutation(() => {
if (!ref.current) return;
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
waitForTransitionEnd(ref.current, dispatchHeavyAnimationStop);
const endHeavyAnimation = beginHeavyAnimation();
waitForTransitionEnd(ref.current, endHeavyAnimation);
onOpenAnimationStart?.();

View File

@ -1,6 +1,7 @@
import '../../global/actions/all';
import React, {
beginHeavyAnimation,
memo, useEffect, useLayoutEffect,
useRef, useState,
} from '../../lib/teact/teact';
@ -42,7 +43,6 @@ import useInterval from '../../hooks/schedulers/useInterval';
import useTimeout from '../../hooks/schedulers/useTimeout';
import useAppLayout from '../../hooks/useAppLayout';
import useForceUpdate from '../../hooks/useForceUpdate';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useLastCallback from '../../hooks/useLastCallback';
import usePreventPinchZoomGesture from '../../hooks/usePreventPinchZoomGesture';
import useShowTransition from '../../hooks/useShowTransition';
@ -447,10 +447,10 @@ const Main = ({
});
}
const dispatchHeavyAnimationEnd = dispatchHeavyAnimationEvent();
const endHeavyAnimation = beginHeavyAnimation();
waitForTransitionEnd(document.getElementById('MiddleColumn')!, () => {
dispatchHeavyAnimationEnd();
endHeavyAnimation();
willAnimateLeftColumnRef.current = false;
forceUpdate();
});
@ -480,10 +480,10 @@ const Main = ({
willAnimateRightColumnRef.current = true;
const dispatchHeavyAnimationEnd = dispatchHeavyAnimationEvent();
const endHeavyAnimation = beginHeavyAnimation();
waitForTransitionEnd(document.getElementById('RightColumn')!, () => {
dispatchHeavyAnimationEnd();
endHeavyAnimation();
willAnimateRightColumnRef.current = false;
forceUpdate();
setIsNarrowMessageList(isRightColumnOpen);

View File

@ -1,4 +1,5 @@
import React, {
beginHeavyAnimation,
memo, useEffect, useMemo, useRef,
} from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global';
@ -40,7 +41,6 @@ import useAppLayout from '../../hooks/useAppLayout';
import useElectronDrag from '../../hooks/useElectronDrag';
import useFlag from '../../hooks/useFlag';
import useForceUpdate from '../../hooks/useForceUpdate';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang';
import { exitPictureInPictureIfNeeded, usePictureInPictureSignal } from '../../hooks/usePictureInPicture';
@ -216,12 +216,12 @@ const MediaViewer = ({
useEffect(() => {
if (isGhostAnimation && isOpen && (shouldAnimateOpening || !prevItem)) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateOpening(hasFooter, origin!, bestImageData!, dimensions!, isVideo, message, mediaIndex);
}
if (isGhostAnimation && !isOpen && prevItem) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateClosing(prevOrigin!, prevBestImageData!, prevMessage, prevItem?.mediaIndex);
}
}, [

View File

@ -1,5 +1,6 @@
import type { FC } from '../../lib/teact/teact';
import React, {
beginHeavyAnimation,
memo, useEffect, useLayoutEffect, useRef,
} from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global';
@ -13,7 +14,6 @@ import buildClassName from '../../util/buildClassName';
import { IS_ANDROID } from '../../util/windowEnvironment';
import useFlag from '../../hooks/useFlag';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
@ -74,11 +74,11 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
}, [handleCancelAnimation]);
useLayoutEffect(() => {
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
const endHeavyAnimation = beginHeavyAnimation();
timeoutRef.current = setTimeout(() => {
stop();
dispatchHeavyAnimationStop();
endHeavyAnimation();
}, PLAYING_DURATION);
}, [stop]);

View File

@ -1,5 +1,6 @@
import type { FC } from '../../lib/teact/teact';
import React, {
beginHeavyAnimation,
memo,
useEffect,
useMemo,
@ -66,7 +67,6 @@ import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
import useInterval from '../../hooks/schedulers/useInterval';
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useLastCallback from '../../hooks/useLastCallback';
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
import useNativeCopySelectedMessages from '../../hooks/useNativeCopySelectedMessages';
@ -629,7 +629,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
useEffectWithPrevDeps(([prevIsSelectModeActive]) => {
if (prevIsSelectModeActive !== undefined) {
dispatchHeavyAnimationEvent(SELECT_MODE_ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(SELECT_MODE_ANIMATION_DURATION + ANIMATION_END_DELAY);
}
}, [isSelectModeActive]);

View File

@ -1,6 +1,6 @@
import type { RefObject } from 'react';
import type { FC } from '../../lib/teact/teact';
import React, { memo } from '../../lib/teact/teact';
import React, { getIsHeavyAnimating, memo } from '../../lib/teact/teact';
import { getActions } from '../../global';
import type { MessageListType } from '../../global/types';
@ -25,7 +25,6 @@ import { isAlbum } from './helpers/groupMessages';
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
import useDerivedSignal from '../../hooks/useDerivedSignal';
import { getIsHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useMessageObservers from './hooks/useMessageObservers';

View File

@ -1,6 +1,7 @@
import type { ChangeEvent, RefObject } from 'react';
import type { FC } from '../../../lib/teact/teact';
import React, {
getIsHeavyAnimating,
memo, useEffect, useLayoutEffect,
useRef, useState,
} from '../../../lib/teact/teact';
@ -28,7 +29,6 @@ import { isSelectionInsideInput } from './helpers/selection';
import useAppLayout from '../../../hooks/useAppLayout';
import useDerivedState from '../../../hooks/useDerivedState';
import useFlag from '../../../hooks/useFlag';
import { isHeavyAnimating } from '../../../hooks/useHeavyAnimationCheck';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useInputCustomEmojis from './hooks/useInputCustomEmojis';
@ -265,7 +265,7 @@ const MessageInput: FC<OwnProps & StateProps> = ({
return;
}
if (isHeavyAnimating()) {
if (getIsHeavyAnimating()) {
setTimeout(focusInput, FOCUS_DELAY_MS);
return;
}

View File

@ -1,11 +1,7 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
beginHeavyAnimation,
memo, useCallback, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
@ -126,7 +122,6 @@ import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
import useEnsureMessage from '../../../hooks/useEnsureMessage';
import useEnsureStory from '../../../hooks/useEnsureStory';
import useFlag from '../../../hooks/useFlag';
import { dispatchHeavyAnimationEvent } from '../../../hooks/useHeavyAnimationCheck';
import { useOnIntersect } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
@ -832,7 +827,7 @@ const Message: FC<OwnProps & StateProps> = ({
const container = entry.target.closest<HTMLDivElement>('.MessageList');
if (!container) return;
dispatchHeavyAnimationEvent(RESIZE_ANIMATION_DURATION);
beginHeavyAnimation(RESIZE_ANIMATION_DURATION);
const resizeDiff = newHeight - lastHeight;
const { offsetHeight, scrollHeight, scrollTop } = container;

View File

@ -1,8 +1,8 @@
import { useEffect, useRef } from '../../../../lib/teact/teact';
import { getIsHeavyAnimating, useEffect, useRef } from '../../../../lib/teact/teact';
import { requestMeasure } from '../../../../lib/fasterdom/fasterdom';
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../../../hooks/useHeavyAnimationCheck';
import useHeavyAnimation from '../../../../hooks/useHeavyAnimation';
import useLastCallback from '../../../../hooks/useLastCallback';
import usePriorityPlaybackCheck, { isPriorityPlaybackActive } from '../../../../hooks/usePriorityPlaybackCheck';
import useBackgroundMode, { isBackgroundModeActive } from '../../../../hooks/window/useBackgroundMode';
@ -26,7 +26,7 @@ export default function useVideoAutoPause(
});
useBackgroundMode(pause, unfreezePlayingOnRaf, !canPlay || isPriority);
useHeavyAnimationCheck(pause, unfreezePlaying, !canPlay || isPriority);
useHeavyAnimation(pause, unfreezePlaying, !canPlay || isPriority);
usePriorityPlaybackCheck(pause, unfreezePlaying, !canPlay || isPriority);
const handlePlaying = useLastCallback(() => {
@ -81,5 +81,5 @@ function usePlayPause(mediaRef: React.RefObject<HTMLMediaElement>) {
}
function isFrozen() {
return isHeavyAnimating() || isPriorityPlaybackActive() || isBackgroundModeActive();
return getIsHeavyAnimating() || isPriorityPlaybackActive() || isBackgroundModeActive();
}

View File

@ -1,4 +1,6 @@
import React, { memo, useEffect, useMemo } from '../../lib/teact/teact';
import React, {
beginHeavyAnimation, memo, useEffect, useMemo,
} from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global';
import type { ApiChat, ApiUser } from '../../api/types';
@ -8,7 +10,6 @@ import { ANIMATION_END_DELAY, PREVIEW_AVATAR_COUNT } from '../../config';
import { selectIsForumPanelOpen, selectPerformanceSettingsValue, selectTabState } from '../../global/selectors';
import { animateClosing, animateOpening, ANIMATION_DURATION } from './helpers/ribbonAnimation';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useStoryPreloader from './hooks/useStoryPreloader';
@ -98,10 +99,10 @@ function StoryToggler({
useEffect(() => {
if (!withAnimation || isForumPanelOpen) return;
if (isVisible) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateClosing(isArchived);
} else {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateOpening(isArchived);
}
}, [isArchived, isVisible, withAnimation, isForumPanelOpen]);

View File

@ -1,4 +1,5 @@
import React, {
beginHeavyAnimation,
memo, useCallback, useEffect, useState,
} from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global';
@ -19,7 +20,6 @@ import { disableDirectTextInput, enableDirectTextInput } from '../../util/direct
import { animateClosing, animateOpening } from './helpers/ghostAnimation';
import useFlag from '../../hooks/useFlag';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import { dispatchPriorityPlaybackEvent } from '../../hooks/usePriorityPlaybackCheck';
@ -117,11 +117,11 @@ function StoryViewer({
useEffect(() => {
if (isGhostAnimation && !isPrevOpen && isOpen && peerId && thumbnail && origin !== undefined) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateOpening(peerId, origin, thumbnail, bestImageData, slideSizes.activeSlide);
}
if (isGhostAnimation && isPrevOpen && !isOpen && prevPeerId && prevBestImageData && prevOrigin !== undefined) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);
beginHeavyAnimation(ANIMATION_DURATION + ANIMATION_END_DELAY);
animateClosing(prevPeerId, prevOrigin, prevBestImageData);
}
}, [

View File

@ -1,4 +1,5 @@
import React, {
beginHeavyAnimation,
type FC, memo, useEffect, useRef,
} from '../../lib/teact/teact';
@ -11,7 +12,6 @@ import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMe
import useAppLayout from '../../hooks/useAppLayout';
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useHistoryBack from '../../hooks/useHistoryBack';
import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation';
import useLastCallback from '../../hooks/useLastCallback';
@ -100,7 +100,7 @@ const Menu: FC<OwnProps> = ({
useEffectWithPrevDeps(([prevIsOpen]) => {
if (isOpen || (!isOpen && prevIsOpen === true)) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION);
beginHeavyAnimation(ANIMATION_DURATION);
}
}, [isOpen]);

View File

@ -1,5 +1,5 @@
import type { FC, TeactNode } from '../../lib/teact/teact';
import React, { useEffect } from '../../lib/teact/teact';
import React, { beginHeavyAnimation, useEffect } from '../../lib/teact/teact';
import type { TextPart } from '../../types';
@ -9,7 +9,6 @@ import { disableDirectTextInput, enableDirectTextInput } from '../../util/direct
import freezeWhenClosed from '../../util/hoc/freezeWhenClosed';
import trapFocus from '../../util/trapFocus';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useHistoryBack from '../../hooks/useHistoryBack';
import useLastCallback from '../../hooks/useLastCallback';
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
@ -110,7 +109,7 @@ const Modal: FC<OwnProps> = ({
document.body.classList.toggle('has-open-dialog', Boolean(isOpen));
if (isOpen || (!isOpen && prevIsOpen !== undefined)) {
dispatchHeavyAnimationEvent(ANIMATION_DURATION);
beginHeavyAnimation(ANIMATION_DURATION);
}
return () => {

View File

@ -1,5 +1,7 @@
import type { RefObject } from 'react';
import React, { useEffect, useLayoutEffect, useRef } from '../../lib/teact/teact';
import React, {
beginHeavyAnimation, useEffect, useLayoutEffect, useRef,
} from '../../lib/teact/teact';
import {
addExtraClass, removeExtraClass, setExtraStyles, toggleExtraClass,
} from '../../lib/teact/teact-dom';
@ -14,7 +16,6 @@ import { omit } from '../../util/iteratees';
import { allowSwipeControlForTransition } from '../../util/swipeController';
import useForceUpdate from '../../hooks/useForceUpdate';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import './Transition.scss';
@ -233,7 +234,7 @@ function Transition({
});
isAnimatingRef.current = true;
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
const endHeavyAnimation = beginHeavyAnimation();
onStart?.();
toggleExtraClass(container, `Transition-${name}`, !isBackwards);
@ -245,7 +246,7 @@ function Transition({
requestMutation(() => {
if (activeKey !== currentKeyRef.current) {
dispatchHeavyAnimationStop();
endHeavyAnimation();
return;
}
@ -269,7 +270,7 @@ function Transition({
}
onStop?.();
dispatchHeavyAnimationStop();
endHeavyAnimation();
isAnimatingRef.current = false;
cleanup();
@ -291,7 +292,7 @@ function Transition({
giveUpAnimationEnd();
isSwipeJustCancelledRef.current = true;
onStop?.();
dispatchHeavyAnimationStop();
endHeavyAnimation();
isAnimatingRef.current = false;
},
);
@ -424,7 +425,7 @@ function performSlideOptimized(
}
isAnimatingRef.current = true;
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
const endHeavyAnimation = beginHeavyAnimation();
onStart?.();
toggleExtraClass(container, `Transition-${name}`, !isBackwards);
@ -473,7 +474,7 @@ function performSlideOptimized(
requestMutation(() => {
if (activeKey !== currentKeyRef.current) {
dispatchHeavyAnimationStop();
endHeavyAnimation();
return;
}
@ -490,7 +491,7 @@ function performSlideOptimized(
}
onStop?.();
dispatchHeavyAnimationStop();
endHeavyAnimation();
isAnimatingRef.current = false;
cleanup();

View File

@ -1,4 +1,5 @@
/* eslint-disable eslint-multitab-tt/no-immediate-global */
import { getIsHeavyAnimating, onFullyIdle } from '../lib/teact/teact';
import { addCallback, removeCallback } from '../lib/teact/teactn';
import type { ApiAvailableReaction, ApiMessage } from '../api/types';
@ -44,7 +45,6 @@ import {
} from './selectors';
import { getIsMobile } from '../hooks/useAppLayout';
import { isHeavyAnimating, onFullyIdle } from '../hooks/useHeavyAnimationCheck';
const UPDATE_THROTTLE = 5000;
@ -249,7 +249,7 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
function updateCache(force?: boolean) {
const global = getGlobal();
if (isRemovingCache || !isCaching || global.isLoggingOut || (!force && isHeavyAnimating())) {
if (isRemovingCache || !isCaching || global.isLoggingOut || (!force && getIsHeavyAnimating())) {
return;
}

View File

@ -1,7 +1,9 @@
import { useCallback, useRef, useState } from '../lib/teact/teact';
import {
getIsHeavyAnimating, useCallback, useRef, useState,
} from '../lib/teact/teact';
import useForceUpdate from './useForceUpdate';
import useHeavyAnimationCheck, { isHeavyAnimating } from './useHeavyAnimationCheck';
import useHeavyAnimation from './useHeavyAnimation';
import useRunDebounced from './useRunDebounced';
import useSyncEffect from './useSyncEffect';
@ -43,10 +45,10 @@ function useHeavyAnimationFreeze() {
isPending.current = false;
forceUpdate();
}, [forceUpdate]);
useHeavyAnimationCheck(noop, handleUnfreeze);
useHeavyAnimation(noop, handleUnfreeze);
return {
isFrozen: isHeavyAnimating(),
isFrozen: getIsHeavyAnimating(),
updateWhenUnfrozen,
};
}

View File

@ -1,26 +1,23 @@
import {
getIsHeavyAnimating,
useCallback, useEffect, useMemo, useRef,
} from '../lib/teact/teact';
import { requestMeasure } from '../lib/fasterdom/fasterdom';
import { createCallbackManager } from '../util/callbacks';
import { onIdle } from '../util/schedulers';
import { createSignal } from '../util/signals';
import useLastCallback from './useLastCallback';
// Make sure to end even if end callback was not called (which was some hardly-reproducible bug)
const AUTO_END_TIMEOUT = 1000;
export const startCallbacks = createCallbackManager();
export const endCallbacks = createCallbackManager();
const startCallbacks = createCallbackManager();
const endCallbacks = createCallbackManager();
getIsHeavyAnimating.subscribe(() => {
if (getIsHeavyAnimating()) {
startCallbacks.runCallbacks();
} else {
endCallbacks.runCallbacks();
}
});
let counter = 0;
const [getIsAnimating, setIsAnimating] = createSignal(false);
export const getIsHeavyAnimating = getIsAnimating;
export default function useHeavyAnimationCheck(
export default function useHeavyAnimation(
onStart?: AnyToVoidFunction,
onEnd?: AnyToVoidFunction,
isDisabled = false,
@ -33,7 +30,7 @@ export default function useHeavyAnimationCheck(
return undefined;
}
if (getIsAnimating()) {
if (getIsHeavyAnimating()) {
lastOnStart();
}
@ -57,7 +54,7 @@ export function useThrottleForHeavyAnimation<T extends AnyToVoidFunction>(afterH
return useMemo(() => {
return (...args: Parameters<T>) => {
if (!isScheduledRef.current) {
if (!getIsAnimating()) {
if (!getIsHeavyAnimating()) {
fnMemo(...args);
return;
}
@ -73,48 +70,3 @@ export function useThrottleForHeavyAnimation<T extends AnyToVoidFunction>(afterH
};
}, [fnMemo]);
}
export function isHeavyAnimating() {
return getIsAnimating();
}
export function dispatchHeavyAnimationEvent(duration = AUTO_END_TIMEOUT) {
counter++;
if (counter === 1) {
setIsAnimating(true);
startCallbacks.runCallbacks();
}
const timeout = window.setTimeout(onEnd, duration);
let hasEnded = false;
function onEnd() {
if (hasEnded) return;
hasEnded = true;
clearTimeout(timeout);
counter--;
if (counter === 0) {
setIsAnimating(false);
endCallbacks.runCallbacks();
}
}
return onEnd;
}
export function onFullyIdle(cb: NoneToVoidFunction) {
onIdle(() => {
if (getIsAnimating()) {
requestMeasure(() => {
onFullyIdle(cb);
});
} else {
cb();
}
});
}

View File

@ -7,7 +7,7 @@ import { type CallbackManager, createCallbackManager } from '../util/callbacks';
import {
debounce, throttle, throttleWith,
} from '../util/schedulers';
import useHeavyAnimationCheck from './useHeavyAnimationCheck';
import useHeavyAnimation from './useHeavyAnimation';
import useLastCallback from './useLastCallback';
type TargetCallback = (entry: IntersectionObserverEntry) => void;
@ -71,7 +71,7 @@ export function useIntersectionObserver({
}
});
useHeavyAnimationCheck(freeze, unfreeze);
useHeavyAnimation(freeze, unfreeze);
useEffect(() => {
if (isDisabled) {

View File

@ -1,7 +1,6 @@
import { useEffect, useSignal } from '../lib/teact/teact';
import { getIsHeavyAnimating, useEffect, useSignal } from '../lib/teact/teact';
import useDerivedState from './useDerivedState';
import { getIsHeavyAnimating } from './useHeavyAnimationCheck';
export default function useMountAfterHeavyAnimation(hasIntersected: boolean) {
const [getNoHeavyAnimation, setNoHeavyAnimation] = useSignal(false);

View File

@ -1,8 +1,7 @@
import type { RefObject } from 'react';
import { useEffect } from '../lib/teact/teact';
import { onFullyIdle, useEffect } from '../lib/teact/teact';
import unloadVideo from '../util/browser/unloadVideo';
import { onFullyIdle } from './useHeavyAnimationCheck';
// Fix for memory leak when unmounting video element
export default function useVideoCleanup(videoRef: RefObject<HTMLVideoElement>, dependencies: any[]) {

View File

@ -0,0 +1,50 @@
import { onIdle } from '../../util/schedulers';
import { createSignal } from '../../util/signals';
import { requestMeasure } from '../fasterdom/fasterdom';
const AUTO_END_TIMEOUT = 1000;
let counter = 0;
const [getIsAnimating, setIsAnimating] = createSignal(false);
export const getIsHeavyAnimating = getIsAnimating;
export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT) {
counter++;
if (counter === 1) {
setIsAnimating(true);
}
const timeout = window.setTimeout(onEnd, duration);
let hasEnded = false;
function onEnd() {
if (hasEnded) return;
hasEnded = true;
clearTimeout(timeout);
counter--;
if (counter === 0) {
setIsAnimating(false);
}
}
return onEnd;
}
export function onFullyIdle(cb: NoneToVoidFunction) {
onIdle(() => {
if (getIsAnimating()) {
requestMeasure(() => {
onFullyIdle(cb);
});
} else {
cb();
}
});
}

View File

@ -9,6 +9,8 @@ import { throttleWith } from '../../util/schedulers';
import { createSignal, isSignal, type Signal } from '../../util/signals';
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
export { getIsHeavyAnimating, beginHeavyAnimation, onFullyIdle } from './heavyAnimation';
export type Props = AnyLiteral;
export type FC<P extends Props = any> = (props: P) => any;
// eslint-disable-next-line @typescript-eslint/naming-convention

View File

@ -6,10 +6,9 @@ import { handleError } from '../../util/handleError';
import { orderBy } from '../../util/iteratees';
import { throttleWithTickEnd } from '../../util/schedulers';
import { requestMeasure } from '../fasterdom/fasterdom';
import React, { DEBUG_resolveComponentName, useEffect } from './teact';
import React, { DEBUG_resolveComponentName, getIsHeavyAnimating, useEffect } from './teact';
import useForceUpdate from '../../hooks/useForceUpdate';
import { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
import useUniqueId from '../../hooks/useUniqueId';
export default React;
@ -75,7 +74,7 @@ let forceOnHeavyAnimation = true;
function runCallbacks() {
if (forceOnHeavyAnimation) {
forceOnHeavyAnimation = false;
} else if (isHeavyAnimating()) {
} else if (getIsHeavyAnimating()) {
requestMeasure(runCallbacksThrottled);
return;
}

View File

@ -1,3 +1,4 @@
import { beginHeavyAnimation } from '../lib/teact/teact';
import { getGlobal } from '../global';
import type { ScrollTargetPosition } from '../types';
@ -14,13 +15,11 @@ import { selectCanAnimateInterface } from '../global/selectors';
import { animateSingle, cancelSingleAnimation } from './animation';
import { IS_ANDROID } from './windowEnvironment';
import { dispatchHeavyAnimationEvent } from '../hooks/useHeavyAnimationCheck';
type Params = Parameters<typeof createMutateFunction>;
let isAnimating = false;
let currentArgs: Parameters<typeof createMutateFunction> | undefined;
let onHeavyAnimationStop: NoneToVoidFunction | undefined;
let onHeavyAnimationEnd: NoneToVoidFunction | undefined;
export default function animateScroll(...args: Params | [...Params, boolean]) {
currentArgs = args.slice(0, 8) as Params;
@ -127,9 +126,9 @@ function createMutateFunction(
isAnimating = true;
const prevOnHeavyAnimationStop = onHeavyAnimationStop;
onHeavyAnimationStop = dispatchHeavyAnimationEvent();
prevOnHeavyAnimationStop?.();
const prevOnHeavyAnimationEnd = onHeavyAnimationEnd;
onHeavyAnimationEnd = beginHeavyAnimation();
prevOnHeavyAnimationEnd?.();
animateSingle(() => {
const t = Math.min((Date.now() - startAt) / duration, 1);
@ -143,8 +142,8 @@ function createMutateFunction(
if (!isAnimating) {
currentArgs = undefined;
onHeavyAnimationStop!();
onHeavyAnimationStop = undefined;
onHeavyAnimationEnd!();
onHeavyAnimationEnd = undefined;
}
return isAnimating;

View File

@ -1,3 +1,4 @@
import { onFullyIdle } from '../lib/teact/teact';
import { addCallback } from '../lib/teact/teactn';
import { addActionHandler, getGlobal } from '../global';
@ -23,8 +24,6 @@ import { createCallbackManager } from './callbacks';
import { areSortedArraysEqual, unique } from './iteratees';
import { throttle } from './schedulers';
import { onFullyIdle } from '../hooks/useHeavyAnimationCheck';
interface FolderSummary {
id: number;
listIds?: Set<string>;

View File

@ -1,4 +1,5 @@
/* eslint-disable eslint-multitab-tt/set-global-only-variable */
import { onFullyIdle } from '../lib/teact/teact';
import { addCallback } from '../lib/teact/teactn';
import { getActions, getGlobal, setGlobal } from '../global';
@ -24,8 +25,6 @@ import { getCurrentTabId, signalPasscodeHash, subscribeToTokenDied } from './est
import { omit } from './iteratees';
import { IS_MULTITAB_SUPPORTED } from './windowEnvironment';
import { onFullyIdle } from '../hooks/useHeavyAnimationCheck';
type BroadcastChannelRefreshLangpack = {
type: 'langpackRefresh';
langCode: string;