[Perf] Re-implement useShowTransition to avoid re-renders

f-u
This commit is contained in:
Alexander Zinchuk 2024-09-06 15:43:12 +02:00
parent 9b5c527a8a
commit 63f1ca396d
67 changed files with 411 additions and 285 deletions

View File

@ -17,7 +17,7 @@ import { getSuggestedLanguage } from './helpers/getSuggestedLanguage';
import useAsync from '../../hooks/useAsync';
import useFlag from '../../hooks/useFlag';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import useOldLangString from '../../hooks/useOldLangString';
@ -90,7 +90,7 @@ const AuthCode: FC<StateProps> = ({
});
}, []);
const transitionClassNames = useMediaTransition(isQrMounted);
const transitionClassNames = useMediaTransitionDeprecated(isQrMounted);
useLayoutEffect(() => {
if (!authQrCode || !qrCode) {

View File

@ -12,7 +12,7 @@ import buildClassName from '../../../util/buildClassName';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import AvatarList from '../../common/AvatarList';
import Button from '../../ui/Button';
@ -89,7 +89,7 @@ const GroupCallTopPane: FC<OwnProps & StateProps> = ({
const {
shouldRender,
transitionClassNames,
} = useShowTransition(Boolean(groupCall && isActive));
} = useShowTransitionDeprecated(Boolean(groupCall && isActive));
const renderingParticipantCount = useCurrentOrPrev(groupCall?.participantsCount, true);
const renderingFetchedParticipants = useCurrentOrPrev(fetchedParticipants, true);

View File

@ -6,7 +6,7 @@ import buildClassName from '../../util/buildClassName';
import useFlag from '../../hooks/useFlag';
import useLastCallback from '../../hooks/useLastCallback';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import AnimatedSticker from './AnimatedSticker';
@ -29,7 +29,7 @@ function AnimatedIcon(props: OwnProps) {
...otherProps
} = props;
const [isAnimationLoaded, markAnimationLoaded] = useFlag(false);
const transitionClassNames = useMediaTransition(noTransition || isAnimationLoaded);
const transitionClassNames = useMediaTransitionDeprecated(noTransition || isAnimationLoaded);
const handleLoad = useLastCallback(() => {
markAnimationLoaded();

View File

@ -7,7 +7,7 @@ import buildStyle from '../../util/buildStyle';
import useFlag from '../../hooks/useFlag';
import useLastCallback from '../../hooks/useLastCallback';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import AnimatedIcon from './AnimatedIcon';
@ -27,10 +27,10 @@ function AnimatedIconWithPreview(props: OwnProps) {
} = props;
const [isThumbOpen, , unmarkThumbOpen] = useFlag(Boolean(thumbDataUri));
const thumbClassNames = useMediaTransition(isThumbOpen);
const thumbClassNames = useMediaTransitionDeprecated(isThumbOpen);
const [isPreviewOpen, markPreviewOpen, unmarkPreviewOpen] = useFlag(loadedPreviewUrls.has(previewUrl));
const previewClassNames = useMediaTransition(isPreviewOpen);
const previewClassNames = useMediaTransitionDeprecated(isPreviewOpen);
const [isAnimationReady, markAnimationReady] = useFlag(false);

View File

@ -38,7 +38,7 @@ import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import Button from '../ui/Button';
import Link from '../ui/Link';
@ -213,7 +213,7 @@ const Audio: FC<OwnProps> = ({
const {
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransition(isTransferring);
} = useShowTransitionDeprecated(isTransferring);
const shouldRenderCross = shouldRenderSpinner && (isLoadingForPlaying || isUploading);

View File

@ -34,7 +34,7 @@ import renderText from './helpers/renderText';
import { useFastClick } from '../../hooks/useFastClick';
import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import OptimizedVideo from '../ui/OptimizedVideo';
@ -160,7 +160,7 @@ const Avatar: FC<OwnProps> = ({
// `videoBlobUrl` can be taken from memory cache, so we need to check `shouldLoadVideo` again
const shouldPlayVideo = Boolean(videoBlobUrl && shouldLoadVideo);
const transitionClassNames = useMediaTransition(hasBlobUrl);
const transitionClassNames = useMediaTransitionDeprecated(hasBlobUrl);
const handleVideoEnded = useLastCallback((e) => {
const video = e.currentTarget;

View File

@ -124,7 +124,7 @@ import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useSchedule from '../../hooks/useSchedule';
import useSendMessageAction from '../../hooks/useSendMessageAction';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import { useStateRef } from '../../hooks/useStateRef';
import useSyncEffect from '../../hooks/useSyncEffect';
import useAttachmentModal from '../middle/composer/hooks/useAttachmentModal';
@ -1425,7 +1425,7 @@ const Composer: FC<OwnProps & StateProps> = ({
const {
shouldRender: shouldRenderReactionSelector,
transitionClassNames: reactionSelectorTransitonClassNames,
} = useShowTransition(isReactionSelectorOpen);
} = useShowTransitionDeprecated(isReactionSelectorOpen);
const areVoiceMessagesNotAllowed = mainButtonState === MainButtonState.Record
&& (!canAttachMedia || !canSendVoiceByPrivacy || !canSendVoices);

View File

@ -14,9 +14,9 @@ import renderText from './helpers/renderText';
import useAppLayout from '../../hooks/useAppLayout';
import useCanvasBlur from '../../hooks/useCanvasBlur';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import Link from '../ui/Link';
import ProgressSpinner from '../ui/ProgressSpinner';
@ -75,12 +75,12 @@ const File: FC<OwnProps> = ({
const [withThumb] = useState(!previewData);
const noThumb = Boolean(previewData);
const thumbRef = useCanvasBlur(thumbnailDataUri, noThumb, isMobile && !IS_CANVAS_FILTER_SUPPORTED);
const thumbClassNames = useMediaTransition(!noThumb);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const {
shouldRender: shouldSpinnerRender,
transitionClassNames: spinnerClassNames,
} = useShowTransition(isTransferring, undefined, true);
} = useShowTransitionDeprecated(isTransferring, undefined, true);
const color = getColorFromExtension(extension);
const sizeString = getFileSizeString(size);

View File

@ -19,7 +19,7 @@ import useFlag from '../../hooks/useFlag';
import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import MediaSpoiler from './MediaSpoiler';
@ -46,7 +46,7 @@ const Media: FC<OwnProps> = ({
const isIntersecting = useIsIntersecting(ref, observeIntersection);
const thumbDataUri = getMessageMediaThumbDataUri(message);
const mediaBlobUrl = useMedia(getMessageMediaHash(message, 'pictogram'), !isIntersecting);
const transitionClassNames = useMediaTransition(mediaBlobUrl);
const transitionClassNames = useMediaTransitionDeprecated(mediaBlobUrl);
const video = getMessageVideo(message);

View File

@ -6,7 +6,7 @@ import buildClassName from '../../util/buildClassName';
import useCanvasBlur from '../../hooks/useCanvasBlur';
import useLastCallback from '../../hooks/useLastCallback';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import styles from './MediaSpoiler.module.scss';
@ -33,7 +33,7 @@ const MediaSpoiler: FC<OwnProps> = ({
// eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(
isVisible, undefined, true, withAnimation ? false : undefined, undefined, ANIMATION_DURATION,
);
const canvasRef = useCanvasBlur(thumbDataUri, !shouldRender, undefined, BLUR_RADIUS, width, height);

View File

@ -5,7 +5,7 @@ import buildClassName from '../../util/buildClassName';
import renderText from './helpers/renderText';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import './NothingFound.scss';
@ -18,7 +18,7 @@ const DEFAULT_TEXT = 'Nothing found.';
const NothingFound: FC<OwnProps> = ({ text = DEFAULT_TEXT, description }) => {
const lang = useOldLang();
const { transitionClassNames } = useShowTransition(true);
const { transitionClassNames } = useShowTransitionDeprecated(true);
return (
<div className={buildClassName('NothingFound', transitionClassNames, description && 'with-description')}>

View File

@ -14,7 +14,7 @@ import stopEvent from '../../util/stopEvent';
import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import './Media.scss';
@ -42,7 +42,7 @@ const PreviewMedia: FC<OwnProps> = ({
const thumbDataUri = getMessageMediaThumbDataUri(media);
const mediaBlobUrl = useMedia(getMessageMediaHash(media, 'preview'), !isIntersecting);
const transitionClassNames = useMediaTransition(mediaBlobUrl);
const transitionClassNames = useMediaTransitionDeprecated(mediaBlobUrl);
const video = media.content.video;

View File

@ -27,7 +27,7 @@ import useAppLayout from '../../hooks/useAppLayout';
import useCanvasBlur from '../../hooks/useCanvasBlur';
import useFlag from '../../hooks/useFlag';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import OptimizedVideo from '../ui/OptimizedVideo';
@ -82,7 +82,7 @@ const ProfilePhoto: FC<OwnProps> = ({
const fullMediaData = videoBlobUrl || photoBlobUrl;
const [isVideoReady, markVideoReady] = useFlag();
const isFullMediaReady = Boolean(fullMediaData && (!isVideo || isVideoReady));
const transitionClassNames = useMediaTransition(isFullMediaReady);
const transitionClassNames = useMediaTransitionDeprecated(isFullMediaReady);
const isBlurredThumb = canHaveMedia && !isFullMediaReady && !previewBlobUrl && photo?.thumbnail?.dataUri;
const blurredThumbCanvasRef = useCanvasBlur(
photo?.thumbnail?.dataUri, !isBlurredThumb, isMobile && !IS_CANVAS_FILTER_SUPPORTED,

View File

@ -13,7 +13,7 @@ import buildClassName from '../../util/buildClassName';
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import AnimatedIconWithPreview from './AnimatedIconWithPreview';
import CustomEmoji from './CustomEmoji';
@ -61,7 +61,7 @@ const ReactionEmoji: FC<OwnProps> = ({
onClick(reaction);
});
const transitionClassNames = useMediaTransition(mediaData);
const transitionClassNames = useMediaTransitionDeprecated(mediaData);
const fullClassName = buildClassName(
styles.root,
isSelected && styles.selected,

View File

@ -9,7 +9,7 @@ import { isSameReaction } from '../../global/helpers';
import buildClassName from '../../util/buildClassName';
import useMedia from '../../hooks/useMedia';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import CustomEmoji from './CustomEmoji';
@ -41,7 +41,7 @@ const ReactionStaticEmoji: FC<OwnProps> = ({
const staticIconId = availableReaction?.staticIcon?.id;
const mediaData = useMedia(`document${staticIconId}`, !staticIconId, ApiMediaFormat.BlobUrl);
const transitionClassNames = useMediaTransition(mediaData);
const transitionClassNames = useMediaTransitionDeprecated(mediaData);
const shouldApplySizeFix = 'emoticon' in reaction && reaction.emoticon === '🦄';
const shouldReplaceWithHeartIcon = withIconHeart && 'emoticon' in reaction && reaction.emoticon === '❤';

View File

@ -27,7 +27,7 @@ import useAppLayout from '../../hooks/useAppLayout';
import useFlag from '../../hooks/useFlag';
import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
import useLastCallback from '../../hooks/useLastCallback';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import useResizeObserver from '../../hooks/useResizeObserver';
import useWindowSize from '../../hooks/window/useWindowSize';
@ -138,7 +138,7 @@ const StickerSet: FC<OwnProps> = ({
const [itemsPerRow, setItemsPerRow] = useState(getItemsPerRowFallback(windowWidth));
const isIntersecting = useIsIntersecting(ref, observeIntersection ?? observeIntersectionForShowingItems);
const transitionClassNames = useMediaTransition(isIntersecting);
const transitionClassNames = useMediaTransitionDeprecated(isIntersecting);
// `isNearActive` is set in advance during animation, but it is not reliable for short sets
const shouldRender = isNearActive || isIntersecting;

View File

@ -123,9 +123,13 @@ const StickerView: FC<OwnProps> = ({
const thumbData = cachedPreview || previewMediaData || thumbDataUri;
const isThumbOpaque = sharedCanvasRef && !withTranslucentThumb;
const thumbClassNames = useMediaTransition(thumbData && !isFullMediaReady);
const fullMediaClassNames = useMediaTransition(isFullMediaReady);
const noTransition = isLottie && withPreview;
const noCrossTransition = Boolean(isLottie && withPreview);
const thumbRef = useMediaTransition<HTMLImageElement>(thumbData && !isFullMediaReady, {
noCloseTransition: noCrossTransition,
});
const fullMediaRef = useMediaTransition<HTMLElement>(isFullMediaReady, {
noOpenTransition: noCrossTransition,
});
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);
@ -144,13 +148,13 @@ const StickerView: FC<OwnProps> = ({
return (
<>
<img
ref={thumbRef}
src={thumbData}
className={buildClassName(
styles.thumb,
noTransition && styles.noTransition,
noCrossTransition && styles.noTransition,
isThumbOpaque && styles.thumbOpaque,
thumbClassName,
thumbClassNames,
'sticker-media',
)}
alt=""
@ -158,14 +162,14 @@ const StickerView: FC<OwnProps> = ({
/>
{shouldRenderFullMedia && (isLottie ? (
<AnimatedSticker
ref={fullMediaRef as React.RefObject<HTMLDivElement>}
key={renderId}
renderId={renderId}
size={size}
className={buildClassName(
styles.media,
(noTransition || isThumbOpaque) && styles.noTransition,
(noCrossTransition || isThumbOpaque) && styles.noTransition,
fullMediaClassName,
fullMediaClassNames,
)}
tgsUrl={fullMediaData}
play={shouldPlay}
@ -182,8 +186,9 @@ const StickerView: FC<OwnProps> = ({
/>
) : isVideo ? (
<OptimizedVideo
ref={fullMediaRef as React.RefObject<HTMLVideoElement>}
canPlay={shouldPlay}
className={buildClassName(styles.media, fullMediaClassName, fullMediaClassNames, 'sticker-media')}
className={buildClassName(styles.media, fullMediaClassName, 'sticker-media')}
src={fullMediaData}
playsInline
muted
@ -197,7 +202,8 @@ const StickerView: FC<OwnProps> = ({
/>
) : (
<img
className={buildClassName(styles.media, fullMediaClassName, fullMediaClassNames, 'sticker-media')}
ref={fullMediaRef as React.RefObject<HTMLImageElement>}
className={buildClassName(styles.media, fullMediaClassName, 'sticker-media')}
src={fullMediaData}
alt={emoji}
style={filterStyle}

View File

@ -17,7 +17,7 @@ import { pause } from '../../util/schedulers';
import useEffectOnce from '../../hooks/useEffectOnce';
import useFlag from '../../hooks/useFlag';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
// Workaround for incorrect bundling by Webpack: force including in the main chunk
import '../ui/Modal.scss';
@ -110,7 +110,7 @@ const UiLoader: FC<OwnProps & StateProps> = ({
const [isReady, markReady] = useFlag();
const {
shouldRender: shouldRenderMask, transitionClassNames,
} = useShowTransition(!isReady, undefined, true);
} = useShowTransitionDeprecated(!isReady, undefined, true);
useEffectOnce(() => {
let timeout: number | undefined;

View File

@ -16,7 +16,7 @@ import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useCustomEmoji from '../hooks/useCustomEmoji';
import AnimatedSticker from '../AnimatedSticker';
@ -125,11 +125,11 @@ const ReactionAnimatedEmoji = ({
const {
shouldRender: shouldRenderEffect,
transitionClassNames: animationClassNames,
} = useShowTransition(shouldPlayEffect, undefined, true, 'slow');
} = useShowTransitionDeprecated(shouldPlayEffect, undefined, true, 'slow');
const {
shouldRender: shouldRenderCenter,
transitionClassNames: centerAnimationClassNames,
} = useShowTransition(shouldPlayCenter, undefined, true, 'slow');
} = useShowTransitionDeprecated(shouldPlayCenter, undefined, true, 'slow');
const handleEnded = useLastCallback(() => {
stopActiveReaction({ containerId, reaction });
@ -140,7 +140,7 @@ const ReactionAnimatedEmoji = ({
const {
shouldRender: shouldRenderStatic,
transitionClassNames: staticClassNames,
} = useShowTransition(shouldShowStatic, undefined, true);
} = useShowTransitionDeprecated(shouldShowStatic, undefined, true);
const rootClassName = buildClassName(
styles.root,

View File

@ -14,7 +14,7 @@ import useForumPanelRender from '../../hooks/useForumPanelRender';
import useHistoryBack from '../../hooks/useHistoryBack';
import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useLeftHeaderButtonRtlForumTransition from './main/hooks/useLeftHeaderButtonRtlForumTransition';
import StoryRibbon from '../story/StoryRibbon';
@ -70,7 +70,7 @@ const ArchivedChats: FC<OwnProps> = ({
const {
shouldRender: shouldRenderTitle,
transitionClassNames: titleClassNames,
} = useShowTransition(!isForumPanelOpen);
} = useShowTransitionDeprecated(!isForumPanelOpen);
const {
shouldRenderForumPanel, handleForumPanelAnimationEnd,
@ -82,7 +82,9 @@ const ArchivedChats: FC<OwnProps> = ({
shouldRender: shouldRenderStoryRibbon,
transitionClassNames: storyRibbonClassNames,
isClosing: isStoryRibbonClosing,
} = useShowTransition(isStoryRibbonShown, undefined, undefined, '', false, ANIMATION_DURATION + ANIMATION_END_DELAY);
} = useShowTransitionDeprecated(
isStoryRibbonShown, undefined, undefined, '', false, ANIMATION_DURATION + ANIMATION_END_DELAY,
);
return (
<div className="ArchivedChats">

View File

@ -57,7 +57,7 @@ import useEnsureMessage from '../../../hooks/useEnsureMessage';
import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useChatListEntry from './hooks/useChatListEntry';
import Avatar from '../../common/Avatar';
@ -290,7 +290,7 @@ const Chat: FC<OwnProps & StateProps> = ({
}, [chat, chatId, isForum, isIntersecting]);
const isOnline = user && userStatus && isUserOnline(user, userStatus);
const { hasShownClass: isAvatarOnlineShown } = useShowTransition(isOnline);
const { hasShownClass: isAvatarOnlineShown } = useShowTransitionDeprecated(isOnline);
const href = useMemo(() => {
if (!IS_OPEN_IN_NEW_TAB_SUPPORTED) return undefined;

View File

@ -24,7 +24,7 @@ import { useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManag
import useHistoryBack from '../../../hooks/useHistoryBack';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import StoryRibbon from '../../story/StoryRibbon';
import TabList from '../../ui/TabList';
@ -103,7 +103,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
shouldRender: shouldRenderStoryRibbon,
transitionClassNames: storyRibbonClassNames,
isClosing: isStoryRibbonClosing,
} = useShowTransition(isStoryRibbonShown, undefined, undefined, '');
} = useShowTransitionDeprecated(isStoryRibbonShown, undefined, undefined, '');
const allChatsFolder: ApiChatFolder = useMemo(() => {
return {
@ -283,7 +283,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
const {
shouldRender: shouldRenderPlaceholder, transitionClassNames,
} = useShowTransition(!orderedFolderIds, undefined, true);
} = useShowTransitionDeprecated(!orderedFolderIds, undefined, true);
function renderCurrentTab(isActive: boolean) {
const activeFolder = Object.values(chatFoldersById)

View File

@ -15,7 +15,7 @@ import { IS_ELECTRON, IS_TOUCH_ENV } from '../../../util/windowEnvironment';
import useForumPanelRender from '../../../hooks/useForumPanelRender';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import Button from '../../ui/Button';
import Transition from '../../ui/Transition';
@ -86,7 +86,7 @@ const LeftMain: FC<OwnProps> = ({
const {
shouldRender: shouldRenderUpdateButton,
transitionClassNames: updateButtonClassNames,
} = useShowTransition(isAppUpdateAvailable || isElectronUpdateAvailable);
} = useShowTransitionDeprecated(isAppUpdateAvailable || isElectronUpdateAvailable);
const isMouseInside = useRef(false);

View File

@ -17,7 +17,7 @@ import useCanvasBlur from '../../../hooks/useCanvasBlur';
import useMedia from '../../../hooks/useMedia';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import ProgressSpinner from '../../ui/ProgressSpinner';
@ -41,7 +41,7 @@ const WallpaperTile: FC<OwnProps> = ({
const localBlobUrl = document.previewBlobUrl;
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
const thumbRef = useCanvasBlur(document.thumbnail?.dataUri, Boolean(previewBlobUrl), true);
const { transitionClassNames } = useShowTransition(
const { transitionClassNames } = useShowTransitionDeprecated(
Boolean(previewBlobUrl || localBlobUrl),
undefined,
undefined,
@ -53,7 +53,7 @@ const WallpaperTile: FC<OwnProps> = ({
mediaData: fullMedia, loadProgress,
} = useMediaWithLoadProgress(localMediaHash, !isLoadAllowed);
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
const { shouldRender: shouldRenderSpinner, transitionClassNames: spinnerClassNames } = useShowTransition(
const { shouldRender: shouldRenderSpinner, transitionClassNames: spinnerClassNames } = useShowTransitionDeprecated(
(isLoadAllowed && !fullMedia) || slug === UPLOADING_WALLPAPER_SLUG,
undefined,
wasLoadDisabled,

View File

@ -12,7 +12,7 @@ import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets';
import useTimeout from '../../hooks/schedulers/useTimeout';
import useFlag from '../../hooks/useFlag';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import AnimatedIconWithPreview from '../common/AnimatedIconWithPreview';
import PasswordForm from '../common/PasswordForm';
@ -55,7 +55,7 @@ const LockScreen: FC<OwnProps & StateProps> = ({
const [validationError, setValidationError] = useState<string>('');
const [shouldShowPasscode, setShouldShowPasscode] = useState(false);
const [isSignOutDialogOpen, openSignOutConfirmation, closeSignOutConfirmation] = useFlag(false);
const { shouldRender } = useShowTransition(isLocked);
const { shouldRender } = useShowTransitionDeprecated(isLocked);
useTimeout(resetInvalidUnlockAttempts, timeoutUntil ? timeoutUntil - Date.now() : undefined);

View File

@ -7,18 +7,12 @@ import React, {
import { addExtraClass } from '../../lib/teact/teact-dom';
import { getActions, getGlobal, withGlobal } from '../../global';
import type {
ApiChatFolder,
ApiMessage,
ApiUser,
} from '../../api/types';
import type { ApiChatFolder, ApiMessage, ApiUser } from '../../api/types';
import type { ApiLimitTypeWithModal, TabState } from '../../global/types';
import type { LangCode } from '../../types';
import { ElectronEvent } from '../../types/electron';
import {
BASE_EMOJI_KEYWORD_LANG, DEBUG, INACTIVE_MARKER,
} from '../../config';
import { BASE_EMOJI_KEYWORD_LANG, DEBUG, INACTIVE_MARKER } from '../../config';
import { requestNextMutation } from '../../lib/fasterdom/fasterdom';
import {
selectCanAnimateInterface,
@ -430,9 +424,12 @@ const Main = ({
}
}, []);
const leftColumnTransition = useShowTransition(
isLeftColumnOpen, undefined, true, undefined, shouldSkipHistoryAnimations, undefined, true,
);
useShowTransition({
ref: containerRef,
isOpen: isLeftColumnOpen,
noCloseTransition: shouldSkipHistoryAnimations,
prefix: 'left-column-',
});
const willAnimateLeftColumnRef = useRef(false);
const forceUpdate = useForceUpdate();
@ -459,9 +456,12 @@ const Main = ({
});
}, [isLeftColumnOpen, withInterfaceAnimations, forceUpdate]);
const rightColumnTransition = useShowTransition(
isRightColumnOpen, undefined, true, undefined, shouldSkipHistoryAnimations, undefined, true,
);
useShowTransition({
ref: containerRef,
isOpen: isRightColumnOpen,
noCloseTransition: shouldSkipHistoryAnimations,
prefix: 'right-column-',
});
const willAnimateRightColumnRef = useRef(false);
const [isNarrowMessageList, setIsNarrowMessageList] = useState(isRightColumnOpen);
@ -491,11 +491,7 @@ const Main = ({
}, [isMiddleColumnOpen, isRightColumnOpen, noRightColumnAnimation, forceUpdate]);
const className = buildClassName(
leftColumnTransition.hasShownClass && 'left-column-shown',
leftColumnTransition.hasOpenClass && 'left-column-open',
willAnimateLeftColumnRef.current && 'left-column-animating',
rightColumnTransition.hasShownClass && 'right-column-shown',
rightColumnTransition.hasOpenClass && 'right-column-open',
willAnimateRightColumnRef.current && 'right-column-animating',
isNarrowMessageList && 'narrow-message-list',
shouldSkipHistoryAnimations && 'history-animation-disabled',

View File

@ -7,7 +7,7 @@ import buildClassName from '../../../../util/buildClassName';
import useCanvasBlur from '../../../../hooks/useCanvasBlur';
import useMedia from '../../../../hooks/useMedia';
import useMediaTransition from '../../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../../hooks/useMediaTransitionDeprecated';
import OptimizedVideo from '../../../ui/OptimizedVideo';
@ -34,7 +34,7 @@ const PremiumFeaturePreviewVideo: FC<OwnProps> = ({
}) => {
const mediaData = useMedia(`document${videoId}`);
const thumbnailRef = useCanvasBlur(videoThumbnail.dataUri);
const transitionClassNames = useMediaTransition(mediaData);
const transitionClassNames = useMediaTransitionDeprecated(mediaData);
return (
<div className={styles.root}>

View File

@ -17,7 +17,7 @@ import useBuffering from '../../hooks/useBuffering';
import useCurrentTimeSignal from '../../hooks/useCurrentTimeSignal';
import useLastCallback from '../../hooks/useLastCallback';
import usePictureInPicture from '../../hooks/usePictureInPicture';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useVideoCleanup from '../../hooks/useVideoCleanup';
import useFullscreen from '../../hooks/window/useFullscreen';
import useControlsSignal from './hooks/useControlsSignal';
@ -126,11 +126,15 @@ const VideoPlayer: FC<OwnProps> = ({
const {
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransition(!isBuffered && !isUnsupported, undefined, undefined, 'slow');
} = useShowTransitionDeprecated(
!isBuffered && !isUnsupported, undefined, undefined, 'slow',
);
const {
shouldRender: shouldRenderPlayButton,
transitionClassNames: playButtonClassNames,
} = useShowTransition(IS_IOS && !isPlaying && !shouldRenderSpinner && !isUnsupported, undefined, undefined, 'slow');
} = useShowTransitionDeprecated(
IS_IOS && !isPlaying && !shouldRenderSpinner && !isUnsupported, undefined, undefined, 'slow',
);
useEffect(() => {
lockControls(shouldRenderSpinner);

View File

@ -38,7 +38,7 @@ import useEnsureMessage from '../../hooks/useEnsureMessage';
import useFlag from '../../hooks/useFlag';
import { useIsIntersecting, useOnIntersect } from '../../hooks/useIntersectionObserver';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useFocusMessage from './message/hooks/useFocusMessage';
import AnimatedIconFromSticker from '../common/AnimatedIconFromSticker';
@ -161,7 +161,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
}
}, [isVisible, requestConfetti]);
const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false);
const { transitionClassNames } = useShowTransitionDeprecated(isShown, undefined, noAppearanceAnimation, false);
// No need for expensive global updates on users and chats, so we avoid them
const usersById = getGlobal().users.byId;

View File

@ -43,7 +43,7 @@ import useFlag from '../../hooks/useFlag';
import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang';
import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import DeleteChatModal from '../common/DeleteChatModal';
import ReportModal from '../common/ReportModal';
@ -211,7 +211,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
const [shouldRenderMuteModal, markRenderMuteModal, unmarkRenderMuteModal] = useFlag();
const { x, y } = anchor;
useShowTransition(isOpen, onCloseAnimationEnd, undefined, false);
useShowTransitionDeprecated(isOpen, onCloseAnimationEnd, undefined, false);
const isViewGroupInfoShown = usePrevDuringAnimation(
(!isChatInfoShown && isForum) ? true : undefined, CLOSE_MENU_ANIMATION_DURATION,
);

View File

@ -63,7 +63,7 @@ import useLastCallback from '../../hooks/useLastCallback';
import useLongPress from '../../hooks/useLongPress';
import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useWindowSize from '../../hooks/window/useWindowSize';
import GroupCallTopPane from '../calls/group/GroupCallTopPane';
@ -310,20 +310,20 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
const {
shouldRender: shouldShowChatReportPanel,
transitionClassNames: chatReportPanelClassNames,
} = useShowTransition(hasChatSettings);
} = useShowTransitionDeprecated(hasChatSettings);
const renderingChatSettings = useCurrentOrPrev(hasChatSettings ? settings : undefined, true);
const {
shouldRender: shouldRenderAudioPlayer,
transitionClassNames: audioPlayerClassNames,
} = useShowTransition(Boolean(audioMessage));
} = useShowTransitionDeprecated(Boolean(audioMessage));
const renderingAudioMessage = useCurrentOrPrev(audioMessage, true);
const {
shouldRender: shouldRenderPinnedMessage,
transitionClassNames: pinnedMessageClassNames,
} = useShowTransition(Boolean(pinnedMessage) && !isMiddleSearchOpen, undefined, true);
} = useShowTransitionDeprecated(Boolean(pinnedMessage) && !isMiddleSearchOpen, undefined, true);
const renderingPinnedMessage = useCurrentOrPrev(pinnedMessage, true);
const renderingPinnedMessagesCount = useCurrentOrPrev(pinnedMessagesCount, true);

View File

@ -14,7 +14,7 @@ import freezeWhenClosed from '../../../util/hoc/freezeWhenClosed';
import setTooltipItemVisible from '../../../util/setTooltipItemVisible';
import useLastCallback from '../../../hooks/useLastCallback';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
import ChatCommand from './ChatCommand';
@ -56,7 +56,7 @@ const ChatCommandTooltip: FC<OwnProps> = ({
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const handleSendCommand = useLastCallback(({ botId, command }: ApiBotCommand) => {
// No need for expensive global updates on users and chats, so we avoid them

View File

@ -36,7 +36,7 @@ import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import useMenuPosition from '../../../hooks/useMenuPosition';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import { ClosableEmbeddedMessage } from '../../common/embedded/EmbeddedMessage';
import Icon from '../../common/icons/Icon';
@ -131,7 +131,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
const {
shouldRender, transitionClassNames,
} = useShowTransition(
} = useShowTransitionDeprecated(
isShown && !isReplyToTopicStart && !isReplyToDiscussion,
undefined,
!shouldAnimate,

View File

@ -14,7 +14,7 @@ import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import StickerButton from '../../common/StickerButton';
import Loading from '../../ui/Loading';
@ -52,7 +52,7 @@ const CustomEmojiTooltip: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const prevStickers = usePreviousDeprecated(customEmoji, true);
const displayedStickers = customEmoji || prevStickers;

View File

@ -13,7 +13,7 @@ import getFilesFromDataTransferItems from './helpers/getFilesFromDataTransferIte
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import Portal from '../../ui/Portal';
import DropTarget from './DropTarget';
@ -44,7 +44,7 @@ const DropArea: FC<OwnProps> = ({
// eslint-disable-next-line no-null/no-null
const hideTimeoutRef = useRef<number>(null);
const prevWithQuick = usePreviousDeprecated(withQuick);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen);
const isInAlbum = editingMessage && editingMessage?.groupedId;
useEffect(() => (isOpen ? captureEscKeyListener(onHide) : undefined), [isOpen, onHide]);

View File

@ -10,7 +10,7 @@ import { REM } from '../../common/helpers/mediaDimensions';
import useAppLayout from '../../../hooks/useAppLayout';
import { useOnIntersect } from '../../../hooks/useIntersectionObserver';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../../hooks/useOldLang';
import EmojiButton from './EmojiButton';
@ -38,7 +38,7 @@ const EmojiCategory: FC<OwnProps> = ({
useOnIntersect(ref, observeIntersection);
const transitionClassNames = useMediaTransition(shouldRender);
const transitionClassNames = useMediaTransitionDeprecated(shouldRender);
const lang = useOldLang();
const { isMobile } = useAppLayout();

View File

@ -13,7 +13,7 @@ import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import usePrevDuringAnimation from '../../../hooks/usePrevDuringAnimation';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
import Loading from '../../ui/Loading';
@ -79,7 +79,7 @@ const EmojiTooltip: FC<OwnProps> = ({
}) => {
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const listEmojis: (Emoji | ApiSticker)[] = usePrevDuringAnimation(
emojis.length ? [...customEmojis, ...emojis] : undefined, CLOSE_DURATION,
) || [];

View File

@ -17,7 +17,7 @@ import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
import InfiniteScroll from '../../ui/InfiniteScroll';
@ -71,7 +71,7 @@ const InlineBotTooltip: FC<OwnProps> = ({
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const renderedIsGallery = useCurrentOrPrev(isGallery, shouldRender);
const {
observe: observeIntersection,

View File

@ -9,7 +9,7 @@ import setTooltipItemVisible from '../../../util/setTooltipItemVisible';
import useLastCallback from '../../../hooks/useLastCallback';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
import PrivateChatInfo from '../../common/PrivateChatInfo';
@ -32,7 +32,7 @@ const MentionTooltip: FC<OwnProps> = ({
}) => {
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const handleUserSelect = useLastCallback((userId: string, forceFocus = false) => {
// No need for expensive global updates on users, so we avoid them

View File

@ -17,7 +17,7 @@ import useDynamicColorListener from '../../../hooks/stickers/useDynamicColorList
import useCoordsInSharedCanvas from '../../../hooks/useCoordsInSharedCanvas';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useMedia from '../../../hooks/useMedia';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useCustomEmoji from '../../common/hooks/useCustomEmoji';
import AnimatedSticker from '../../common/AnimatedSticker';
@ -68,7 +68,7 @@ const StickerSetCover: FC<OwnProps> = ({
const mediaHash = ((hasThumbnail && !shouldFallbackToStatic) || hasAnimatedThumb) && `stickerSet${stickerSet.id}`;
const mediaData = useMedia(mediaHash, !isIntersecting);
const isReady = thumbCustomEmojiId || mediaData || staticMediaData;
const transitionClassNames = useMediaTransition(isReady);
const transitionClassNames = useMediaTransitionDeprecated(isReady);
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);

View File

@ -13,7 +13,7 @@ import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useSendMessageAction from '../../../hooks/useSendMessageAction';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import StickerButton from '../../common/StickerButton';
import Loading from '../../ui/Loading';
@ -48,7 +48,7 @@ const StickerTooltip: FC<OwnProps & StateProps> = ({
}) => {
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, undefined, undefined, false);
const prevStickers = usePreviousDeprecated(stickers, true);
const displayedStickers = stickers || prevStickers;
const sendMessageAction = useSendMessageAction(chatId, threadId);

View File

@ -17,7 +17,7 @@ import useAppLayout from '../../../hooks/useAppLayout';
import useLastCallback from '../../../hooks/useLastCallback';
import useMouseInside from '../../../hooks/useMouseInside';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import CustomEmojiPicker from '../../common/CustomEmojiPicker';
import Button from '../../ui/Button';
@ -110,7 +110,7 @@ const SymbolMenu: FC<OwnProps & StateProps> = ({
const { isMobile } = useAppLayout();
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose, undefined, isMobile);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen, onClose, false, false);
const lang = useOldLang();

View File

@ -17,7 +17,7 @@ import { INPUT_CUSTOM_EMOJI_SELECTOR } from './helpers/customEmoji';
import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useVirtualBackdrop from '../../../hooks/useVirtualBackdrop';
import Button from '../../ui/Button';
@ -64,7 +64,7 @@ const TextFormatter: FC<OwnProps> = ({
const containerRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line no-null/no-null
const linkUrlInputRef = useRef<HTMLInputElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isOpen);
const [isLinkControlOpen, openLinkControl, closeLinkControl] = useFlag();
const [linkUrl, setLinkUrl] = useState('');
const [isEditingLink, setIsEditingLink] = useState(false);

View File

@ -25,7 +25,7 @@ import useDerivedState from '../../../hooks/useDerivedState';
import useLastCallback from '../../../hooks/useLastCallback';
import useMenuPosition from '../../../hooks/useMenuPosition';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useSyncEffect from '../../../hooks/useSyncEffect';
import Button from '../../ui/Button';
@ -113,7 +113,7 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
const isShown = useDerivedState(() => {
return Boolean(webPagePreview && getHtml() && !noWebPage && !isDisabled);
}, [isDisabled, getHtml, noWebPage, webPagePreview]);
const { shouldRender, transitionClassNames } = useShowTransition(isShown);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isShown);
const renderingWebPage = useCurrentOrPrev(webPagePreview, true);

View File

@ -10,7 +10,7 @@ import buildClassName from '../../../../util/buildClassName';
import useLastCallback from '../../../../hooks/useLastCallback';
import useMedia from '../../../../hooks/useMedia';
import useMediaTransition from '../../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../../hooks/useMediaTransitionDeprecated';
import BaseResult from './BaseResult';
@ -43,7 +43,7 @@ const MediaResult: FC<OwnProps> = ({
const thumbnailBlobUrl = useMedia(getWebDocumentHash(webThumbnail));
const mediaBlobUrl = useMedia(photo && getPhotoMediaHash(photo, 'pictogram'));
const transitionClassNames = useMediaTransition(mediaBlobUrl || thumbnailBlobUrl);
const transitionClassNames = useMediaTransitionDeprecated(mediaBlobUrl || thumbnailBlobUrl);
const handleClick = useLastCallback(() => {
onClick(inlineResult);

View File

@ -14,7 +14,7 @@ import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import MediaAreaOverlay from '../../story/mediaArea/MediaAreaOverlay';
@ -41,7 +41,7 @@ function BaseStory({
const imgBlobUrl = useMedia(imageHash);
const thumbnail = isLoaded ? (video ? video.thumbnail?.dataUri : story.content.photo?.thumbnail?.dataUri) : undefined;
const mediaUrl = useCurrentOrPrev(imgBlobUrl, true);
const { shouldRender, transitionClassNames } = useShowTransition(Boolean(mediaUrl));
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(Boolean(mediaUrl));
const blurredBackgroundRef = useCanvasBlur(
thumbnail,
isExpired && !isPreview,

View File

@ -63,7 +63,7 @@ import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useSchedule from '../../../hooks/useSchedule';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import PinMessageModal from '../../common/PinMessageModal.async';
import ReportModal from '../../common/ReportModal';
@ -230,7 +230,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
} = getActions();
const lang = useOldLang();
const { transitionClassNames } = useShowTransition(isOpen, onCloseAnimationEnd, undefined, false);
const { transitionClassNames } = useShowTransitionDeprecated(isOpen, onCloseAnimationEnd, undefined, false);
const [isMenuOpen, setIsMenuOpen] = useState(true);
const [isReportModalOpen, setIsReportModalOpen] = useState(false);
const [isPinModalOpen, setIsPinModalOpen] = useState(false);

View File

@ -132,7 +132,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useResizeObserver from '../../../hooks/useResizeObserver';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useTextLanguage from '../../../hooks/useTextLanguage';
import useThrottledCallback from '../../../hooks/useThrottledCallback';
import useDetectChatLanguage from './hooks/useDetectChatLanguage';
@ -473,7 +473,7 @@ const Message: FC<OwnProps & StateProps> = ({
setTimeout(markShown, appearanceOrder * APPEARANCE_DELAY);
}, [appearanceOrder, markShown, noAppearanceAnimation]);
const { transitionClassNames } = useShowTransition(
const { transitionClassNames } = useShowTransitionDeprecated(
isShown || isJustAdded,
undefined,
noAppearanceAnimation && !isJustAdded,

View File

@ -87,7 +87,6 @@ type OwnProps = {
hasCustomEmoji?: boolean;
customEmojiSets?: ApiStickerSet[];
canPlayAnimatedEmojis?: boolean;
noTransition?: boolean;
isInSavedMessages?: boolean;
shouldRenderShowWhen?: boolean;
canLoadReadDate?: boolean;
@ -176,7 +175,6 @@ const MessageContextMenu: FC<OwnProps> = ({
hasCustomEmoji,
customEmojiSets,
canPlayAnimatedEmojis,
noTransition,
isInSavedMessages,
shouldRenderShowWhen,
canLoadReadDate,
@ -353,7 +351,6 @@ const MessageContextMenu: FC<OwnProps> = ({
className={buildClassName(
'MessageContextMenu', 'fluid', withReactions && 'with-reactions',
)}
shouldSkipTransition={noTransition}
onClose={onClose}
onCloseAnimationEnd={onCloseAnimationEnd}
>

View File

@ -22,10 +22,10 @@ import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import MediaSpoiler from '../../common/MediaSpoiler';
@ -106,7 +106,7 @@ const Photo = <T,>({
const noThumb = Boolean(fullMediaData);
const thumbRef = useBlurredMediaThumbRef(photo, noThumb);
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
const thumbClassNames = useMediaTransition(!noThumb);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const thumbDataUri = getMediaThumbUri(photo);
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || photo.isSpoiler);
@ -139,11 +139,11 @@ const Photo = <T,>({
const {
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransition(isTransferring, undefined, wasLoadDisabled, 'slow');
} = useShowTransitionDeprecated(isTransferring, undefined, wasLoadDisabled, 'slow');
const {
shouldRender: shouldRenderDownloadButton,
transitionClassNames: downloadButtonClassNames,
} = useShowTransition(!fullMediaData && !isLoadAllowed);
} = useShowTransitionDeprecated(!fullMediaData && !isLoadAllowed);
const handleClick = useLastCallback((e: React.MouseEvent<HTMLElement>) => {
if (isUploading) {

View File

@ -25,10 +25,10 @@ import { useThrottledSignal } from '../../../hooks/useAsyncResolvers';
import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import Icon from '../../common/icons/Icon';
@ -101,7 +101,7 @@ const RoundVideo: FC<OwnProps> = ({
const hasThumb = Boolean(getMessageMediaThumbDataUri(message));
const noThumb = !hasThumb || isPlayerReady || shouldRenderSpoiler;
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
const thumbClassNames = useMediaTransition(!noThumb);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const thumbDataUri = getMessageMediaThumbDataUri(message);
const isTransferring = (isLoadAllowed && !isPlayerReady) || isDownloading;
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
@ -109,7 +109,7 @@ const RoundVideo: FC<OwnProps> = ({
const {
shouldRender: shouldSpinnerRender,
transitionClassNames: spinnerClassNames,
} = useShowTransition(isTransferring, undefined, wasLoadDisabled);
} = useShowTransitionDeprecated(isTransferring, undefined, wasLoadDisabled);
const [isActivated, setIsActivated] = useState(false);

View File

@ -9,7 +9,7 @@ import buildClassName from '../../../util/buildClassName';
import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import MessageContextMenu from './MessageContextMenu';
@ -34,7 +34,7 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
const { openPremiumModal, showDialog } = getActions();
const [isMenuOpen, , closeMenu] = useFlag(true);
const { transitionClassNames } = useShowTransition(isMenuOpen, onCloseAnimationEnd, undefined, false);
const { transitionClassNames } = useShowTransitionDeprecated(isMenuOpen, onCloseAnimationEnd, undefined, false);
const handleAboutAdsOpen = useLastCallback(() => {
onAboutAdsClick();

View File

@ -23,10 +23,10 @@ import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import MediaSpoiler from '../../common/MediaSpoiler';
@ -130,12 +130,12 @@ const Video = <T,>({
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
const canLoadPreview = isIntersectingForLoading;
const previewBlobUrl = useMedia(previewMediaHash, !canLoadPreview);
const previewClassNames = useMediaTransition((hasThumb || previewBlobUrl) && !isPlayerReady);
const previewClassNames = useMediaTransitionDeprecated((hasThumb || previewBlobUrl) && !isPlayerReady);
const noThumb = Boolean(!hasThumb || previewBlobUrl || isPlayerReady);
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
const blurredBackgroundRef = useBlurredMediaThumbRef(video, !withBlurredBackground);
const thumbClassNames = useMediaTransition(!noThumb);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const isInline = fullMediaData && wasIntersectedRef.current;
@ -156,10 +156,10 @@ const Video = <T,>({
const {
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransition(isTransferring && !isUnsupported, undefined, wasLoadDisabled);
} = useShowTransitionDeprecated(isTransferring && !isUnsupported, undefined, wasLoadDisabled);
const {
transitionClassNames: playButtonClassNames,
} = useShowTransition(Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner));
} = useShowTransitionDeprecated(Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner));
const [playProgress, setPlayProgress] = useState<number>(0);
const handleTimeUpdate = useLastCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {

View File

@ -11,7 +11,7 @@ import buildClassName from '../../../util/buildClassName';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import Audio from '../../common/Audio';
import RoundVideo from '../../middle/message/RoundVideo';
@ -36,7 +36,7 @@ const OneTimeMediaModal = ({
const {
shouldRender,
transitionClassNames,
} = useShowTransition(Boolean(modal));
} = useShowTransitionDeprecated(Boolean(modal));
const handlePlayVoice = useLastCallback(() => {
return undefined;

View File

@ -43,9 +43,9 @@ import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
import useFlag from '../../hooks/useFlag';
import useLastCallback from '../../hooks/useLastCallback';
import useLongPress from '../../hooks/useLongPress';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import { useStreaming } from '../../hooks/useStreaming';
import useBackgroundMode from '../../hooks/window/useBackgroundMode';
import useStoryPreloader from './hooks/useStoryPreloader';
@ -233,30 +233,30 @@ function Story({
const {
shouldRender: shouldRenderSkeleton,
transitionClassNames: skeletonTransitionClassNames,
} = useShowTransition(!hasFullData);
} = useShowTransitionDeprecated(!hasFullData);
const {
transitionClassNames: mediaTransitionClassNames,
} = useShowTransition(Boolean(fullMediaData));
} = useShowTransitionDeprecated(Boolean(fullMediaData));
const thumbRef = useCanvasBlur(thumbnail, !hasThumb);
const previewTransitionClassNames = useMediaTransition(previewBlobUrl);
const previewTransitionClassNames = useMediaTransitionDeprecated(previewBlobUrl);
const {
shouldRender: shouldRenderComposer,
transitionClassNames: composerAppearanceAnimationClassNames,
} = useShowTransition(shouldShowComposer);
} = useShowTransitionDeprecated(shouldShowComposer);
const {
shouldRender: shouldRenderCaptionBackdrop,
transitionClassNames: captionBackdropTransitionClassNames,
} = useShowTransition(hasText && isCaptionExpanded);
} = useShowTransitionDeprecated(hasText && isCaptionExpanded);
const { transitionClassNames: appearanceAnimationClassNames } = useShowTransition(true);
const { transitionClassNames: appearanceAnimationClassNames } = useShowTransitionDeprecated(true);
const {
shouldRender: shouldRenderCaption,
transitionClassNames: captionAppearanceAnimationClassNames,
} = useShowTransition(hasText || hasForwardInfo);
} = useShowTransitionDeprecated(hasText || hasForwardInfo);
const isStreamingSupported = useStreaming(videoRef, fullMediaData, PRIMARY_VIDEO_MIME);

View File

@ -12,7 +12,7 @@ import calcTextLineHeightAndCount from '../../util/element/calcTextLineHeightAnd
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
import useOldLang from '../../hooks/useOldLang';
import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import EmbeddedStoryForward from '../common/embedded/EmbeddedStoryForward';
import MessageText from '../common/MessageText';
@ -65,7 +65,7 @@ function StoryCaption({
}, [isExpanded]);
const canExpand = hasOverflow && !isInExpandedState;
const { shouldRender: shouldRenderShowMore, transitionClassNames } = useShowTransition(
const { shouldRender: shouldRenderShowMore, transitionClassNames } = useShowTransitionDeprecated(
canExpand, undefined, true, 'slow', true,
);

View File

@ -10,7 +10,7 @@ import { animateClosing, animateOpening, ANIMATION_DURATION } from './helpers/ri
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useOldLang from '../../hooks/useOldLang';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useStoryPreloader from './hooks/useStoryPreloader';
import Avatar from '../common/Avatar';
@ -89,7 +89,7 @@ function StoryToggler({
const isVisible = canShow && isShown;
// For some reason, setting 'slow' here also fixes scroll freezes on iOS when collapsing Story Ribbon
const { shouldRender, transitionClassNames } = useShowTransition(isVisible, undefined, undefined, 'slow');
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isVisible, undefined, undefined, 'slow');
useEffect(() => {
if (!withAnimation || isForumPanelOpen) return;

View File

@ -115,7 +115,6 @@ const DropdownMenu: FC<OwnProps> = ({
footer={footer}
autoClose
onClose={handleClose}
shouldSkipTransition={forceOpen}
onCloseAnimationEnd={onHide}
onMouseEnterBackdrop={onMouseEnterBackdrop}
>

View File

@ -1,6 +1,4 @@
import React, {
type FC, memo, useEffect, useRef,
} from '../../lib/teact/teact';
import React, { type FC, memo, useEffect } from '../../lib/teact/teact';
import buildClassName from '../../util/buildClassName';
import buildStyle from '../../util/buildStyle';
@ -38,7 +36,6 @@ type OwnProps = {
positionX?: 'left' | 'right';
positionY?: 'top' | 'bottom';
autoClose?: boolean;
shouldSkipTransition?: boolean;
footer?: string;
noCloseOnBackdrop?: boolean;
backdropExcludedSelector?: string;
@ -50,13 +47,13 @@ type OwnProps = {
onMouseEnterBackdrop?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onMouseLeave?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
withPortal?: boolean;
children: React.ReactNode;
children?: React.ReactNode;
};
const ANIMATION_DURATION = 200;
const Menu: FC<OwnProps> = ({
ref,
ref: externalRef,
containerRef,
shouldCloseFast,
isOpen,
@ -80,27 +77,18 @@ const Menu: FC<OwnProps> = ({
onClose,
onMouseEnter,
onMouseLeave,
shouldSkipTransition,
withPortal,
onMouseEnterBackdrop,
}) => {
// eslint-disable-next-line no-null/no-null
let menuRef = useRef<HTMLDivElement>(null);
if (ref) {
menuRef = ref;
}
const backdropContainerRef = containerRef || menuRef;
const { isTouchScreen } = useAppLayout();
const {
transitionClassNames,
} = useShowTransition(
const { ref: menuRef } = useShowTransition({
isOpen,
ref: externalRef,
onCloseAnimationEnd,
shouldSkipTransition,
undefined,
shouldSkipTransition,
);
});
const backdropContainerRef = containerRef || menuRef;
useEffect(
() => (isOpen ? captureEscKeyListener(onClose) : undefined),
@ -134,7 +122,6 @@ const Menu: FC<OwnProps> = ({
positionY,
positionX,
footer && 'with-footer',
transitionClassNames,
bubbleClassName,
shouldCloseFast && 'close-fast',
);
@ -144,7 +131,9 @@ const Menu: FC<OwnProps> = ({
const handleClick = useLastCallback((e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
if (autoClose) { onClose(); }
if (autoClose) {
onClose();
}
});
const menu = (

View File

@ -1,5 +1,5 @@
import type { FC, TeactNode } from '../../lib/teact/teact';
import React, { useEffect, useRef } from '../../lib/teact/teact';
import React, { useEffect } from '../../lib/teact/teact';
import type { TextPart } from '../../types';
@ -9,6 +9,7 @@ import { disableDirectTextInput, enableDirectTextInput } from '../../util/direct
import freezeWhenClosed from '../../util/hoc/freezeWhenClosed';
import trapFocus from '../../util/trapFocus';
import useDerivedState from '../../hooks/useDerivedState';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useHistoryBack from '../../hooks/useHistoryBack';
import useLastCallback from '../../hooks/useLastCallback';
@ -44,11 +45,7 @@ export type OwnProps = {
onEnter?: () => void;
};
type StateProps = {
shouldSkipHistoryAnimations?: boolean;
};
const Modal: FC<OwnProps & StateProps> = ({
const Modal: FC<OwnProps> = ({
dialogRef,
title,
className,
@ -63,19 +60,19 @@ const Modal: FC<OwnProps & StateProps> = ({
noBackdropClose,
children,
style,
shouldSkipHistoryAnimations,
onClose,
onCloseAnimationEnd,
onEnter,
}) => {
const {
shouldRender,
transitionClassNames,
} = useShowTransition(
isOpen, onCloseAnimationEnd, shouldSkipHistoryAnimations, undefined, shouldSkipHistoryAnimations,
);
// eslint-disable-next-line no-null/no-null
const modalRef = useRef<HTMLDivElement>(null);
ref: modalRef,
getShouldRender,
} = useShowTransition({
isOpen,
onCloseAnimationEnd,
});
const shouldRender = useDerivedState(getShouldRender);
const withCloseButton = hasCloseButton || hasAbsoluteCloseButton;
useEffect(() => {
@ -101,7 +98,7 @@ const Modal: FC<OwnProps & StateProps> = ({
useEffect(() => (
isOpen ? captureKeyboardListeners({ onEsc: onClose, onEnter: handleEnter }) : undefined
), [isOpen, onClose, handleEnter]);
useEffect(() => (isOpen && modalRef.current ? trapFocus(modalRef.current) : undefined), [isOpen]);
useEffect(() => (isOpen && modalRef.current ? trapFocus(modalRef.current) : undefined), [isOpen, modalRef]);
useHistoryBack({
isActive: isOpen,
@ -155,7 +152,6 @@ const Modal: FC<OwnProps & StateProps> = ({
const fullClassName = buildClassName(
'Modal',
className,
transitionClassNames,
noBackdrop && 'transparent-backdrop',
isSlim && 'slim',
);

View File

@ -14,7 +14,7 @@ import { ANIMATION_END_DELAY } from '../../config';
import buildClassName from '../../util/buildClassName';
import captureEscKeyListener from '../../util/captureEscKeyListener';
import useShowTransition from '../../hooks/useShowTransition';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import Button from './Button';
import Portal from './Portal';
@ -45,7 +45,7 @@ const Notification: FC<OwnProps> = ({
const [isOpen, setIsOpen] = useState(true);
// eslint-disable-next-line no-null/no-null
const timerRef = useRef<number | undefined>(null);
const { transitionClassNames } = useShowTransition(isOpen);
const { transitionClassNames } = useShowTransitionDeprecated(isOpen);
const closeAndDismiss = useCallback(() => {
setIsOpen(false);

View File

@ -1,8 +1,7 @@
import type { FC } from '../../lib/teact/teact';
import React, { useRef } from '../../lib/teact/teact';
import buildClassName from '../../util/buildClassName';
import useDerivedState from '../../hooks/useDerivedState';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useShowTransition from '../../hooks/useShowTransition';
@ -17,7 +16,7 @@ type OwnProps = {
shouldAnimateFirstRender?: boolean;
style?: string;
children: React.ReactNode;
ref?: React.LegacyRef<HTMLDivElement>;
ref?: React.RefObject<HTMLDivElement>;
};
const ShowTransition: FC<OwnProps> = ({
@ -31,22 +30,21 @@ const ShowTransition: FC<OwnProps> = ({
noCloseTransition,
shouldAnimateFirstRender,
style,
ref,
ref: externalRef,
}) => {
const prevIsOpen = usePreviousDeprecated(isOpen);
const prevChildren = usePreviousDeprecated(children);
const fromChildrenRef = useRef<React.ReactNode>();
const isFirstRender = prevIsOpen === undefined;
const {
shouldRender,
transitionClassNames,
} = useShowTransition(
isOpen && !isHidden,
undefined,
isFirstRender && !shouldAnimateFirstRender,
isCustom ? false : undefined,
const { ref, getShouldRender } = useShowTransition({
isOpen: isOpen && !isHidden,
ref: externalRef,
noMountTransition: isFirstRender && !shouldAnimateFirstRender,
className: isCustom ? false : undefined,
noCloseTransition,
);
});
const shouldRender = useDerivedState(getShouldRender);
if (prevIsOpen && !isOpen) {
fromChildrenRef.current = prevChildren;
@ -57,7 +55,7 @@ const ShowTransition: FC<OwnProps> = ({
<div
id={id}
ref={ref}
className={buildClassName(className, transitionClassNames)}
className={className}
onClick={onClick}
style={style}
>

View File

@ -1,8 +1,17 @@
import useShowTransition from './useShowTransition';
export default function useMediaTransition(mediaData?: unknown) {
export default function useMediaTransition<RefType extends HTMLElement = HTMLDivElement>(
mediaData?: unknown,
options?: Partial<Parameters<typeof useShowTransition<RefType>>[0]>,
) {
const isMediaReady = Boolean(mediaData);
const { transitionClassNames } = useShowTransition(isMediaReady, undefined, isMediaReady, 'slow');
return transitionClassNames;
const { ref } = useShowTransition<RefType>({
isOpen: isMediaReady,
noMountTransition: isMediaReady,
className: 'slow',
...options,
});
return ref;
}

View File

@ -0,0 +1,8 @@
import useShowTransitionDeprecated from './useShowTransitionDeprecated';
export default function useMediaTransitionDeprecated(mediaData?: unknown) {
const isMediaReady = Boolean(mediaData);
const { transitionClassNames } = useShowTransitionDeprecated(isMediaReady, undefined, isMediaReady, 'slow');
return transitionClassNames;
}

View File

@ -1,75 +1,103 @@
import { useRef, useState } from '../lib/teact/teact';
import type { RefObject } from 'react';
import { useLayoutEffect, useRef, useSignal } from '../lib/teact/teact';
import { addExtraClass, toggleExtraClass } from '../lib/teact/teact-dom';
import buildClassName from '../util/buildClassName';
import { requestMeasure } from '../lib/fasterdom/fasterdom';
import useDerivedSignal from './useDerivedSignal';
import useLastCallback from './useLastCallback';
import { useStateRef } from './useStateRef';
import useSyncEffectWithPrevDeps from './useSyncEffectWithPrevDeps';
const CLOSE_DURATION = 350;
const useShowTransition = (
isOpen = false,
onCloseTransitionEnd?: () => void,
noFirstOpenTransition = false,
className: string | false = 'fast',
type State =
'closed'
| 'scheduled-open'
| 'open'
| 'closing';
export default function useShowTransition<RefType extends HTMLElement = HTMLDivElement>({
isOpen,
ref,
noMountTransition = false,
noOpenTransition = false,
noCloseTransition = false,
closeDuration = CLOSE_DURATION,
noOpenTransition = false,
) => {
const [isClosed, setIsClosed] = useState(!isOpen);
const closeTimeoutRef = useRef<number>();
// СSS class should be added in a separate tick to turn on CSS transition.
const [hasOpenClassName, setHasOpenClassName] = useState(isOpen && noFirstOpenTransition);
className = 'fast',
prefix = '',
onCloseAnimationEnd,
}: {
isOpen: boolean | undefined;
ref?: RefObject<RefType>;
noMountTransition?: boolean;
noOpenTransition?: boolean;
noCloseTransition?: boolean;
closeDuration?: number;
className?: string | false;
prefix?: string;
onCloseAnimationEnd?: NoneToVoidFunction;
}) {
// eslint-disable-next-line no-null/no-null
const localRef = useRef<RefType>(null);
ref ||= localRef;
const closingTimeoutRef = useRef<number>();
const [getState, setState] = useSignal<State | undefined>();
const optionsRef = useStateRef({
closeDuration, noMountTransition, noOpenTransition, noCloseTransition,
});
const onCloseEndLast = useLastCallback(onCloseAnimationEnd);
if (isOpen) {
setIsClosed(false);
setHasOpenClassName(true);
useSyncEffectWithPrevDeps(([prevIsOpen]) => {
const options = optionsRef.current;
if (closeTimeoutRef.current) {
window.clearTimeout(closeTimeoutRef.current);
closeTimeoutRef.current = undefined;
}
} else {
setHasOpenClassName(false);
if (!isClosed && !closeTimeoutRef.current) {
const exec = () => {
setIsClosed(true);
if (onCloseTransitionEnd) {
onCloseTransitionEnd();
}
closeTimeoutRef.current = undefined;
};
if (noCloseTransition) {
exec();
} else {
closeTimeoutRef.current = window.setTimeout(exec, closeDuration);
if (isOpen) {
if (closingTimeoutRef.current) {
clearTimeout(closingTimeoutRef.current);
closingTimeoutRef.current = undefined;
}
if (options.noOpenTransition || (prevIsOpen === undefined && options.noMountTransition)) {
setState('open');
} else {
setState('scheduled-open');
requestMeasure(() => {
setState('open');
});
}
} else if (prevIsOpen === undefined || options.noCloseTransition) {
setState('closed');
} else {
setState('closing');
closingTimeoutRef.current = window.setTimeout(() => {
setState('closed');
onCloseEndLast();
}, options.closeDuration);
}
}
}, [isOpen]);
// `noCloseTransition`, when set to true, should remove the open class immediately
const shouldHaveOpenClassName = (hasOpenClassName && !(noCloseTransition && !isOpen)) || (noOpenTransition && isOpen);
const isClosing = Boolean(closeTimeoutRef.current);
const shouldRender = isOpen || isClosing;
const transitionClassNames = buildClassName(
className && 'opacity-transition',
className,
shouldHaveOpenClassName && 'open',
!shouldHaveOpenClassName && 'not-open',
shouldRender && 'shown',
!shouldRender && 'not-shown',
isClosing && 'closing',
);
useLayoutEffect(() => {
const element = ref.current;
if (!element) return;
return {
shouldRender,
transitionClassNames,
hasShownClass: shouldRender,
hasOpenClass: shouldHaveOpenClassName,
isClosing,
};
};
addExtraClass(element, 'opacity-transition');
if (className !== false) {
addExtraClass(element, className);
}
export default useShowTransition;
const state = getState();
const shouldRender = state !== 'closed';
const hasOpenClass = state === 'open';
const isClosing = state === 'closing';
toggleExtraClass(element, `${prefix}shown`, shouldRender);
toggleExtraClass(element, `${prefix}not-shown`, !shouldRender);
toggleExtraClass(element, `${prefix}open`, hasOpenClass);
toggleExtraClass(element, `${prefix}not-open`, !hasOpenClass);
toggleExtraClass(element, `${prefix}closing`, isClosing);
}, [className, getState, prefix, ref]);
const getShouldRender = useDerivedSignal(() => getState() !== 'closed', [getState]);
return { ref, getShouldRender };
}

View File

@ -0,0 +1,75 @@
import { useRef, useState } from '../lib/teact/teact';
import buildClassName from '../util/buildClassName';
const CLOSE_DURATION = 350;
const useShowTransitionDeprecated = (
isOpen = false,
onCloseTransitionEnd?: () => void,
noFirstOpenTransition = false,
className: string | false = 'fast',
noCloseTransition = false,
closeDuration = CLOSE_DURATION,
noOpenTransition = false,
) => {
const [isClosed, setIsClosed] = useState(!isOpen);
const closeTimeoutRef = useRef<number>();
// СSS class should be added in a separate tick to turn on CSS transition.
const [hasOpenClassName, setHasOpenClassName] = useState(isOpen && noFirstOpenTransition);
if (isOpen) {
setIsClosed(false);
setHasOpenClassName(true);
if (closeTimeoutRef.current) {
window.clearTimeout(closeTimeoutRef.current);
closeTimeoutRef.current = undefined;
}
} else {
setHasOpenClassName(false);
if (!isClosed && !closeTimeoutRef.current) {
const exec = () => {
setIsClosed(true);
if (onCloseTransitionEnd) {
onCloseTransitionEnd();
}
closeTimeoutRef.current = undefined;
};
if (noCloseTransition) {
exec();
} else {
closeTimeoutRef.current = window.setTimeout(exec, closeDuration);
}
}
}
// `noCloseTransition`, when set to true, should remove the open class immediately
const shouldHaveOpenClassName = (hasOpenClassName && !(noCloseTransition && !isOpen)) || (noOpenTransition && isOpen);
const isClosing = Boolean(closeTimeoutRef.current);
const shouldRender = isOpen || isClosing;
const transitionClassNames = buildClassName(
className && 'opacity-transition',
className,
shouldHaveOpenClassName && 'open',
!shouldHaveOpenClassName && 'not-open',
shouldRender && 'shown',
!shouldRender && 'not-shown',
isClosing && 'closing',
);
return {
shouldRender,
transitionClassNames,
hasShownClass: shouldRender,
hasOpenClass: shouldHaveOpenClassName,
isClosing,
};
};
export default useShowTransitionDeprecated;

View File

@ -0,0 +1,19 @@
import { useRef } from '../lib/teact/teact';
import useSyncEffect from './useSyncEffect';
const useLayoutEffectWithPrevDeps = <const T extends readonly any[]>(
cb: (args: T | readonly []) => void, dependencies: T,
) => {
const prevDepsRef = useRef<T>();
return useSyncEffect(() => {
const prevDeps = prevDepsRef.current;
prevDepsRef.current = dependencies;
return cb(prevDeps || []);
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
}, dependencies);
};
export default useLayoutEffectWithPrevDeps;