Photo, Video: Leverage the new useShowTransition

This commit is contained in:
Alexander Zinchuk 2024-09-06 15:43:14 +02:00
parent 63f1ca396d
commit 9d788a2fd2
5 changed files with 51 additions and 46 deletions

View File

@ -8,10 +8,7 @@ import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
import { CUSTOM_APPENDIX_ATTRIBUTE, MESSAGE_CONTENT_SELECTOR } from '../../../config';
import { requestMutation } from '../../../lib/fasterdom/fasterdom';
import {
getMediaFormat,
getMediaThumbUri,
getMediaTransferState,
getPhotoMediaHash,
getMediaFormat, getMediaThumbUri, getMediaTransferState, getPhotoMediaHash,
} from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
@ -22,10 +19,10 @@ import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import MediaSpoiler from '../../common/MediaSpoiler';
@ -105,8 +102,8 @@ const Photo = <T,>({
const [withThumb] = useState(!fullMediaData);
const noThumb = Boolean(fullMediaData);
const thumbRef = useBlurredMediaThumbRef(photo, noThumb);
useMediaTransition(!noThumb, { ref: thumbRef });
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const thumbDataUri = getMediaThumbUri(photo);
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || photo.isSpoiler);
@ -137,13 +134,21 @@ const Photo = <T,>({
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
const {
ref: spinnerRef,
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransitionDeprecated(isTransferring, undefined, wasLoadDisabled, 'slow');
} = useShowTransition({
isOpen: isTransferring,
noMountTransition: wasLoadDisabled,
className: 'slow',
withShouldRender: true,
});
const {
ref: downloadButtonRef,
shouldRender: shouldRenderDownloadButton,
transitionClassNames: downloadButtonClassNames,
} = useShowTransitionDeprecated(!fullMediaData && !isLoadAllowed);
} = useShowTransition({
isOpen: !fullMediaData && !isLoadAllowed,
withShouldRender: true,
});
const handleClick = useLastCallback((e: React.MouseEvent<HTMLElement>) => {
if (isUploading) {
@ -228,19 +233,15 @@ const Photo = <T,>({
/>
)}
{withThumb && (
<canvas
ref={thumbRef}
className={buildClassName('thumbnail', thumbClassNames)}
/>
<canvas ref={thumbRef} className="thumbnail" />
)}
{isProtected && <span className="protector" />}
{shouldRenderSpinner && !shouldRenderDownloadButton && (
<div className={`media-loading ${spinnerClassNames}`}>
<div ref={spinnerRef} className="media-loading">
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
</div>
)}
{shouldRenderDownloadButton
&& <i className={buildClassName('icon', 'icon-download', downloadButtonClassNames)} />}
{shouldRenderDownloadButton && <i ref={downloadButtonRef} className="icon icon-download" />}
<MediaSpoiler
isVisible={isSpoilerShown}
withAnimation

View File

@ -6,10 +6,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
import {
getMediaFormat,
getMediaThumbUri,
getMediaTransferState,
getVideoMediaHash,
getMediaFormat, getMediaThumbUri, getMediaTransferState, getVideoMediaHash,
} from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
@ -23,10 +20,10 @@ import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import MediaSpoiler from '../../common/MediaSpoiler';
@ -130,12 +127,12 @@ const Video = <T,>({
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
const canLoadPreview = isIntersectingForLoading;
const previewBlobUrl = useMedia(previewMediaHash, !canLoadPreview);
const previewClassNames = useMediaTransitionDeprecated((hasThumb || previewBlobUrl) && !isPlayerReady);
const previewRef = useMediaTransition<HTMLImageElement>((hasThumb || previewBlobUrl) && !isPlayerReady);
const noThumb = Boolean(!hasThumb || previewBlobUrl || isPlayerReady);
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
useMediaTransition(!noThumb, { ref: thumbRef });
const blurredBackgroundRef = useBlurredMediaThumbRef(video, !withBlurredBackground);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
const isInline = fullMediaData && wasIntersectedRef.current;
@ -154,12 +151,18 @@ const Video = <T,>({
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
const {
ref: spinnerRef,
shouldRender: shouldRenderSpinner,
transitionClassNames: spinnerClassNames,
} = useShowTransitionDeprecated(isTransferring && !isUnsupported, undefined, wasLoadDisabled);
} = useShowTransition({
isOpen: isTransferring && !isUnsupported,
noMountTransition: wasLoadDisabled,
withShouldRender: true,
});
const {
transitionClassNames: playButtonClassNames,
} = useShowTransitionDeprecated(Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner));
ref: playButtonRef,
} = useShowTransition({
isOpen: Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner),
});
const [playProgress, setPlayProgress] = useState<number>(0);
const handleTimeUpdate = useLastCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {
@ -253,20 +256,18 @@ const Video = <T,>({
/>
)}
<img
ref={previewRef}
src={previewBlobUrl}
className={buildClassName('thumbnail', previewClassNames, withBlurredBackground && 'with-blurred-bg')}
className={buildClassName('thumbnail', withBlurredBackground && 'with-blurred-bg')}
alt=""
style={forcedWidth ? `width: ${forcedWidth}px;` : undefined}
draggable={!isProtected}
/>
{hasThumb && !isPreviewPreloaded && (
<canvas
ref={thumbRef}
className={buildClassName('thumbnail', thumbClassNames)}
/>
<canvas ref={thumbRef} className="thumbnail" />
)}
{isProtected && <span className="protector" />}
<i className={buildClassName('icon', 'icon-large-play', playButtonClassNames)} />
<i ref={playButtonRef} className="icon icon-large-play" />
<MediaSpoiler
isVisible={isSpoilerShown}
withAnimation
@ -276,7 +277,7 @@ const Video = <T,>({
className="media-spoiler"
/>
{shouldRenderSpinner && (
<div className={buildClassName('media-loading', spinnerClassNames)}>
<div ref={spinnerRef} className="media-loading">
<ProgressSpinner
progress={transferProgress}
onClick={handleClickOnSpinner}

View File

@ -9,7 +9,6 @@ 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';
@ -66,12 +65,12 @@ const Modal: FC<OwnProps> = ({
}) => {
const {
ref: modalRef,
getShouldRender,
shouldRender,
} = useShowTransition({
isOpen,
onCloseAnimationEnd,
withShouldRender: true,
});
const shouldRender = useDerivedState(getShouldRender);
const withCloseButton = hasCloseButton || hasAbsoluteCloseButton;

View File

@ -1,7 +1,6 @@
import type { FC } from '../../lib/teact/teact';
import React, { useRef } from '../../lib/teact/teact';
import useDerivedState from '../../hooks/useDerivedState';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useShowTransition from '../../hooks/useShowTransition';
@ -37,14 +36,14 @@ const ShowTransition: FC<OwnProps> = ({
const fromChildrenRef = useRef<React.ReactNode>();
const isFirstRender = prevIsOpen === undefined;
const { ref, getShouldRender } = useShowTransition({
const { ref, shouldRender } = useShowTransition({
isOpen: isOpen && !isHidden,
ref: externalRef,
noMountTransition: isFirstRender && !shouldAnimateFirstRender,
className: isCustom ? false : undefined,
noCloseTransition,
withShouldRender: true,
});
const shouldRender = useDerivedState(getShouldRender);
if (prevIsOpen && !isOpen) {
fromChildrenRef.current = prevChildren;

View File

@ -3,7 +3,7 @@ import { useLayoutEffect, useRef, useSignal } from '../lib/teact/teact';
import { addExtraClass, toggleExtraClass } from '../lib/teact/teact-dom';
import { requestMeasure } from '../lib/fasterdom/fasterdom';
import useDerivedSignal from './useDerivedSignal';
import useDerivedState from './useDerivedState';
import useLastCallback from './useLastCallback';
import { useStateRef } from './useStateRef';
import useSyncEffectWithPrevDeps from './useSyncEffectWithPrevDeps';
@ -26,6 +26,7 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
className = 'fast',
prefix = '',
onCloseAnimationEnd,
withShouldRender,
}: {
isOpen: boolean | undefined;
ref?: RefObject<RefType>;
@ -35,6 +36,7 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
closeDuration?: number;
className?: string | false;
prefix?: string;
withShouldRender?: boolean;
onCloseAnimationEnd?: NoneToVoidFunction;
}) {
// eslint-disable-next-line no-null/no-null
@ -97,7 +99,10 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
toggleExtraClass(element, `${prefix}closing`, isClosing);
}, [className, getState, prefix, ref]);
const getShouldRender = useDerivedSignal(() => getState() !== 'closed', [getState]);
const shouldRender = useDerivedState(
() => (withShouldRender && getState() !== 'closed'),
[withShouldRender, getState],
);
return { ref, getShouldRender };
return { ref, shouldRender };
}