[Perf] Sticker View: Delay full media rendering
This commit is contained in:
parent
28c9d9dc27
commit
3ac3ad394b
@ -1,5 +1,5 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
import React, { memo } from '../../lib/teact/teact';
|
import React, { memo, useRef } from '../../lib/teact/teact';
|
||||||
import { getGlobal } from '../../global';
|
import { getGlobal } from '../../global';
|
||||||
|
|
||||||
import type { ApiSticker } from '../../api/types';
|
import type { ApiSticker } from '../../api/types';
|
||||||
@ -99,24 +99,30 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
&& isIntersectingForLoading
|
&& isIntersectingForLoading
|
||||||
);
|
);
|
||||||
const shouldPlay = isIntersectingForPlaying && !noPlay;
|
const shouldPlay = isIntersectingForPlaying && !noPlay;
|
||||||
|
const hasIntersectedForPlayingRef = useRef(isIntersectingForPlaying);
|
||||||
|
if (!hasIntersectedForPlayingRef.current && isIntersectingForPlaying) {
|
||||||
|
hasIntersectedForPlayingRef.current = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isReadyToMountFullMedia = useMountAfterHeavyAnimation(hasIntersectedForPlayingRef.current);
|
||||||
|
|
||||||
|
const cachedPreview = mediaLoader.getFromMemory(previewMediaHash);
|
||||||
|
const shouldLoadPreview = !customColor && !cachedPreview && (
|
||||||
|
!isReadyToMountFullMedia || isUnsupportedVideo || (isStatic ? isSmall : noPlay)
|
||||||
|
);
|
||||||
|
const previewMediaData = useMedia(previewMediaHash, !shouldLoadPreview);
|
||||||
|
|
||||||
const thumbDataUri = useThumbnail(sticker);
|
const thumbDataUri = useThumbnail(sticker);
|
||||||
// Use preview instead of thumb but only if it's already loaded or when playing an animation is disabled
|
const thumbData = cachedPreview || previewMediaData || thumbDataUri;
|
||||||
const previewMediaDataFromCache: string | undefined = mediaLoader.getFromMemory(previewMediaHash);
|
|
||||||
const previewMediaData = useMedia(previewMediaHash, Boolean(previewMediaDataFromCache || !noPlay));
|
|
||||||
const thumbData = customColor ? thumbDataUri : (previewMediaData || thumbDataUri);
|
|
||||||
|
|
||||||
const shouldForcePreview = isUnsupportedVideo || (isStatic && isSmall);
|
// No need to use full media if preview is enough and available
|
||||||
fullMediaHash = shouldForcePreview ? previewMediaHash : (fullMediaHash || `sticker${id}`);
|
const shouldSkipFullMedia = Boolean(fullMediaHash === previewMediaHash && (cachedPreview || previewMediaData));
|
||||||
|
const fullMediaData = useMedia(fullMediaHash || `sticker${id}`, !shouldLoad || shouldSkipFullMedia);
|
||||||
// If preloaded preview is forced, it will render as thumb, so no need to load it again
|
|
||||||
const shouldSkipFullMedia = Boolean(fullMediaHash === previewMediaHash && previewMediaData);
|
|
||||||
|
|
||||||
const fullMediaData = useMedia(fullMediaHash, !shouldLoad || shouldSkipFullMedia);
|
|
||||||
// If Lottie data is loaded we will only render thumb if it's good enough (from preview)
|
// If Lottie data is loaded we will only render thumb if it's good enough (from preview)
|
||||||
const [isPlayerReady, markPlayerReady] = useFlag(Boolean(isLottie && fullMediaData && !previewMediaData));
|
const [isPlayerReady, markPlayerReady] = useFlag(Boolean(isLottie && fullMediaData && !previewMediaData));
|
||||||
const isReadyToMount = useMountAfterHeavyAnimation();
|
|
||||||
const isFullMediaReady = isReadyToMount && fullMediaData && (isStatic || isPlayerReady);
|
const shouldRenderFullMedia = isReadyToMountFullMedia && fullMediaData;
|
||||||
|
const isFullMediaReady = isReadyToMountFullMedia && fullMediaData && (isStatic || isPlayerReady);
|
||||||
|
|
||||||
const isThumbOpaque = sharedCanvasRef && !withTranslucentThumb;
|
const isThumbOpaque = sharedCanvasRef && !withTranslucentThumb;
|
||||||
const thumbClassNames = useMediaTransition(thumbData && !isFullMediaReady);
|
const thumbClassNames = useMediaTransition(thumbData && !isFullMediaReady);
|
||||||
@ -152,7 +158,7 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
alt=""
|
alt=""
|
||||||
draggable={false}
|
draggable={false}
|
||||||
/>
|
/>
|
||||||
{isReadyToMount && (isLottie ? (
|
{shouldRenderFullMedia && (isLottie ? (
|
||||||
<AnimatedSticker
|
<AnimatedSticker
|
||||||
key={renderId}
|
key={renderId}
|
||||||
renderId={renderId}
|
renderId={renderId}
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
import { useEffect } from '../lib/teact/teact';
|
import { useEffect, useSignal } from '../lib/teact/teact';
|
||||||
|
|
||||||
import useFlag from './useFlag';
|
import useDerivedState from './useDerivedState';
|
||||||
import { getIsHeavyAnimating } from './useHeavyAnimationCheck';
|
import { getIsHeavyAnimating } from './useHeavyAnimationCheck';
|
||||||
|
|
||||||
export default function useMountAfterHeavyAnimation() {
|
export default function useMountAfterHeavyAnimation(hasIntersected: boolean) {
|
||||||
const [isReadyToMount, markReadyToMount] = useFlag(false);
|
const [getNoHeavyAnimation, setNoHeavyAnimation] = useSignal(false);
|
||||||
|
|
||||||
const $getIsHeavyAnimating = getIsHeavyAnimating;
|
const $getIsHeavyAnimating = getIsHeavyAnimating;
|
||||||
|
|
||||||
// Animation is often started right after the mount, so we use effect to check for it on the next frame
|
// Animation is usually started right after the mount, so we use effect to check for it on the next frame
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!$getIsHeavyAnimating()) {
|
if (!$getIsHeavyAnimating()) {
|
||||||
markReadyToMount();
|
setNoHeavyAnimation(true);
|
||||||
}
|
}
|
||||||
}, [$getIsHeavyAnimating]);
|
}, [$getIsHeavyAnimating, setNoHeavyAnimation]);
|
||||||
|
|
||||||
return isReadyToMount;
|
return useDerivedState(() => (getNoHeavyAnimation() && hasIntersected), [getNoHeavyAnimation, hasIntersected]);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user