[Perf] Avatar: Do not render video when not intersecting

This commit is contained in:
Alexander Zinchuk 2022-09-13 09:48:05 +02:00
parent 3ef3a8bdfe
commit 4e5c951372

View File

@ -30,9 +30,10 @@ import useMedia from '../../hooks/useMedia';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import { useIsIntersecting } from '../../hooks/useIntersectionObserver'; import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
import useVideoAutoPause from '../middle/message/hooks/useVideoAutoPause';
import useVideoCleanup from '../../hooks/useVideoCleanup';
import './Avatar.scss'; import './Avatar.scss';
import useVideoAutoPause from '../middle/message/hooks/useVideoAutoPause';
const cn = createClassNameBuilder('Avatar'); const cn = createClassNameBuilder('Avatar');
cn.media = cn('media'); cn.media = cn('media');
@ -80,16 +81,12 @@ const Avatar: FC<OwnProps> = ({
let imageHash: string | undefined; let imageHash: string | undefined;
let videoHash: string | undefined; let videoHash: string | undefined;
const hasVideoAvatar = (user || chat)?.hasVideoAvatar; const withVideo = isIntersecting && !noVideo && user?.isPremium && user?.hasVideoAvatar;
const profilePhoto = (user?.fullInfo?.profilePhoto || chat?.fullInfo?.profilePhoto); const profilePhoto = user?.fullInfo?.profilePhoto;
const shouldShowVideo = !noVideo && Boolean(user?.isPremium && profilePhoto?.isVideo); const shouldLoadVideo = withVideo && profilePhoto?.isVideo;
const shouldPlayVideo = isIntersecting && shouldShowVideo;
const shouldFetchBig = size === 'jumbo'; const shouldFetchBig = size === 'jumbo';
if (!isSavedMessages && !isDeleted) { if (!isSavedMessages && !isDeleted) {
if (shouldShowVideo) {
videoHash = getChatAvatarHash(user!, undefined, 'video');
}
if (user) { if (user) {
imageHash = getChatAvatarHash(user, shouldFetchBig ? 'big' : undefined); imageHash = getChatAvatarHash(user, shouldFetchBig ? 'big' : undefined);
} else if (chat) { } else if (chat) {
@ -97,9 +94,21 @@ const Avatar: FC<OwnProps> = ({
} else if (photo) { } else if (photo) {
imageHash = `photo${photo.id}?size=m`; imageHash = `photo${photo.id}?size=m`;
} }
if (shouldLoadVideo) {
videoHash = getChatAvatarHash(user!, undefined, 'video');
}
} }
const imgBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
const videoBlobUrl = useMedia(videoHash, !shouldLoadVideo, ApiMediaFormat.BlobUrl, lastSyncTime);
const hasBlobUrl = Boolean(imgBlobUrl || videoBlobUrl);
const shouldPlayVideo = Boolean(isIntersecting && videoBlobUrl);
const { transitionClassNames } = useShowTransition(hasBlobUrl, undefined, hasBlobUrl, 'slow');
useVideoAutoPause(videoRef, shouldPlayVideo); useVideoAutoPause(videoRef, shouldPlayVideo);
useVideoCleanup(videoRef, [shouldPlayVideo]);
useEffect(() => { useEffect(() => {
const video = videoRef.current; const video = videoRef.current;
@ -113,16 +122,12 @@ const Avatar: FC<OwnProps> = ({
return () => video.removeEventListener('ended', returnToStart); return () => video.removeEventListener('ended', returnToStart);
}, [noLoop]); }, [noLoop]);
const userId = user?.id;
useEffect(() => { useEffect(() => {
if (isIntersecting && !noVideo && user && hasVideoAvatar && !profilePhoto) { if (withVideo && !profilePhoto) {
loadFullUser({ userId: user.id }); loadFullUser({ userId });
} }
}, [hasVideoAvatar, profilePhoto, loadFullUser, user, noVideo, isIntersecting]); }, [loadFullUser, profilePhoto, userId, withVideo]);
const imgBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
const videoBlobUrl = useMedia(videoHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
const hasBlobUrl = Boolean(imgBlobUrl || videoBlobUrl);
const { transitionClassNames } = useShowTransition(hasBlobUrl, undefined, hasBlobUrl, 'slow');
const lang = useLang(); const lang = useLang();
@ -144,11 +149,11 @@ const Avatar: FC<OwnProps> = ({
alt={author} alt={author}
decoding="async" decoding="async"
/> />
{videoBlobUrl && ( {shouldPlayVideo && (
<video <video
ref={videoRef} ref={videoRef}
src={videoBlobUrl} src={videoBlobUrl}
className={buildClassName(cn.media, 'avatar-media', transitionClassNames)} className={buildClassName(cn.media, 'avatar-media')}
muted muted
autoPlay autoPlay
disablePictureInPicture disablePictureInPicture