Photo, Video: Leverage the new useShowTransition
This commit is contained in:
parent
63f1ca396d
commit
9d788a2fd2
@ -8,10 +8,7 @@ import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
|
|||||||
import { CUSTOM_APPENDIX_ATTRIBUTE, MESSAGE_CONTENT_SELECTOR } from '../../../config';
|
import { CUSTOM_APPENDIX_ATTRIBUTE, MESSAGE_CONTENT_SELECTOR } from '../../../config';
|
||||||
import { requestMutation } from '../../../lib/fasterdom/fasterdom';
|
import { requestMutation } from '../../../lib/fasterdom/fasterdom';
|
||||||
import {
|
import {
|
||||||
getMediaFormat,
|
getMediaFormat, getMediaThumbUri, getMediaTransferState, getPhotoMediaHash,
|
||||||
getMediaThumbUri,
|
|
||||||
getMediaTransferState,
|
|
||||||
getPhotoMediaHash,
|
|
||||||
} from '../../../global/helpers';
|
} from '../../../global/helpers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
||||||
@ -22,10 +19,10 @@ import useFlag from '../../../hooks/useFlag';
|
|||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
|
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
|
||||||
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
|
import useMediaTransition from '../../../hooks/useMediaTransition';
|
||||||
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
||||||
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
|
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
|
||||||
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||||
|
|
||||||
import MediaSpoiler from '../../common/MediaSpoiler';
|
import MediaSpoiler from '../../common/MediaSpoiler';
|
||||||
@ -105,8 +102,8 @@ const Photo = <T,>({
|
|||||||
const [withThumb] = useState(!fullMediaData);
|
const [withThumb] = useState(!fullMediaData);
|
||||||
const noThumb = Boolean(fullMediaData);
|
const noThumb = Boolean(fullMediaData);
|
||||||
const thumbRef = useBlurredMediaThumbRef(photo, noThumb);
|
const thumbRef = useBlurredMediaThumbRef(photo, noThumb);
|
||||||
|
useMediaTransition(!noThumb, { ref: thumbRef });
|
||||||
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
|
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
|
||||||
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
|
|
||||||
const thumbDataUri = getMediaThumbUri(photo);
|
const thumbDataUri = getMediaThumbUri(photo);
|
||||||
|
|
||||||
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || photo.isSpoiler);
|
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || photo.isSpoiler);
|
||||||
@ -137,13 +134,21 @@ const Photo = <T,>({
|
|||||||
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
|
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
ref: spinnerRef,
|
||||||
shouldRender: shouldRenderSpinner,
|
shouldRender: shouldRenderSpinner,
|
||||||
transitionClassNames: spinnerClassNames,
|
} = useShowTransition({
|
||||||
} = useShowTransitionDeprecated(isTransferring, undefined, wasLoadDisabled, 'slow');
|
isOpen: isTransferring,
|
||||||
|
noMountTransition: wasLoadDisabled,
|
||||||
|
className: 'slow',
|
||||||
|
withShouldRender: true,
|
||||||
|
});
|
||||||
const {
|
const {
|
||||||
|
ref: downloadButtonRef,
|
||||||
shouldRender: shouldRenderDownloadButton,
|
shouldRender: shouldRenderDownloadButton,
|
||||||
transitionClassNames: downloadButtonClassNames,
|
} = useShowTransition({
|
||||||
} = useShowTransitionDeprecated(!fullMediaData && !isLoadAllowed);
|
isOpen: !fullMediaData && !isLoadAllowed,
|
||||||
|
withShouldRender: true,
|
||||||
|
});
|
||||||
|
|
||||||
const handleClick = useLastCallback((e: React.MouseEvent<HTMLElement>) => {
|
const handleClick = useLastCallback((e: React.MouseEvent<HTMLElement>) => {
|
||||||
if (isUploading) {
|
if (isUploading) {
|
||||||
@ -228,19 +233,15 @@ const Photo = <T,>({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{withThumb && (
|
{withThumb && (
|
||||||
<canvas
|
<canvas ref={thumbRef} className="thumbnail" />
|
||||||
ref={thumbRef}
|
|
||||||
className={buildClassName('thumbnail', thumbClassNames)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{isProtected && <span className="protector" />}
|
{isProtected && <span className="protector" />}
|
||||||
{shouldRenderSpinner && !shouldRenderDownloadButton && (
|
{shouldRenderSpinner && !shouldRenderDownloadButton && (
|
||||||
<div className={`media-loading ${spinnerClassNames}`}>
|
<div ref={spinnerRef} className="media-loading">
|
||||||
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
|
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{shouldRenderDownloadButton
|
{shouldRenderDownloadButton && <i ref={downloadButtonRef} className="icon icon-download" />}
|
||||||
&& <i className={buildClassName('icon', 'icon-download', downloadButtonClassNames)} />}
|
|
||||||
<MediaSpoiler
|
<MediaSpoiler
|
||||||
isVisible={isSpoilerShown}
|
isVisible={isSpoilerShown}
|
||||||
withAnimation
|
withAnimation
|
||||||
|
|||||||
@ -6,10 +6,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
|||||||
import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
|
import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getMediaFormat,
|
getMediaFormat, getMediaThumbUri, getMediaTransferState, getVideoMediaHash,
|
||||||
getMediaThumbUri,
|
|
||||||
getMediaTransferState,
|
|
||||||
getVideoMediaHash,
|
|
||||||
} from '../../../global/helpers';
|
} from '../../../global/helpers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { formatMediaDuration } from '../../../util/dates/dateFormat';
|
import { formatMediaDuration } from '../../../util/dates/dateFormat';
|
||||||
@ -23,10 +20,10 @@ import useFlag from '../../../hooks/useFlag';
|
|||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
import useMedia from '../../../hooks/useMedia';
|
||||||
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
|
import useMediaTransition from '../../../hooks/useMediaTransition';
|
||||||
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
||||||
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
|
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
|
||||||
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||||
|
|
||||||
import MediaSpoiler from '../../common/MediaSpoiler';
|
import MediaSpoiler from '../../common/MediaSpoiler';
|
||||||
@ -130,12 +127,12 @@ const Video = <T,>({
|
|||||||
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
|
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
|
||||||
const canLoadPreview = isIntersectingForLoading;
|
const canLoadPreview = isIntersectingForLoading;
|
||||||
const previewBlobUrl = useMedia(previewMediaHash, !canLoadPreview);
|
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 noThumb = Boolean(!hasThumb || previewBlobUrl || isPlayerReady);
|
||||||
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
|
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
|
||||||
|
useMediaTransition(!noThumb, { ref: thumbRef });
|
||||||
const blurredBackgroundRef = useBlurredMediaThumbRef(video, !withBlurredBackground);
|
const blurredBackgroundRef = useBlurredMediaThumbRef(video, !withBlurredBackground);
|
||||||
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
|
|
||||||
|
|
||||||
const isInline = fullMediaData && wasIntersectedRef.current;
|
const isInline = fullMediaData && wasIntersectedRef.current;
|
||||||
|
|
||||||
@ -154,12 +151,18 @@ const Video = <T,>({
|
|||||||
|
|
||||||
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
|
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
|
||||||
const {
|
const {
|
||||||
|
ref: spinnerRef,
|
||||||
shouldRender: shouldRenderSpinner,
|
shouldRender: shouldRenderSpinner,
|
||||||
transitionClassNames: spinnerClassNames,
|
} = useShowTransition({
|
||||||
} = useShowTransitionDeprecated(isTransferring && !isUnsupported, undefined, wasLoadDisabled);
|
isOpen: isTransferring && !isUnsupported,
|
||||||
|
noMountTransition: wasLoadDisabled,
|
||||||
|
withShouldRender: true,
|
||||||
|
});
|
||||||
const {
|
const {
|
||||||
transitionClassNames: playButtonClassNames,
|
ref: playButtonRef,
|
||||||
} = useShowTransitionDeprecated(Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner));
|
} = useShowTransition({
|
||||||
|
isOpen: Boolean((isLoadAllowed || fullMediaData) && !isPlayAllowed && !shouldRenderSpinner),
|
||||||
|
});
|
||||||
|
|
||||||
const [playProgress, setPlayProgress] = useState<number>(0);
|
const [playProgress, setPlayProgress] = useState<number>(0);
|
||||||
const handleTimeUpdate = useLastCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {
|
const handleTimeUpdate = useLastCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {
|
||||||
@ -253,20 +256,18 @@ const Video = <T,>({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<img
|
<img
|
||||||
|
ref={previewRef}
|
||||||
src={previewBlobUrl}
|
src={previewBlobUrl}
|
||||||
className={buildClassName('thumbnail', previewClassNames, withBlurredBackground && 'with-blurred-bg')}
|
className={buildClassName('thumbnail', withBlurredBackground && 'with-blurred-bg')}
|
||||||
alt=""
|
alt=""
|
||||||
style={forcedWidth ? `width: ${forcedWidth}px;` : undefined}
|
style={forcedWidth ? `width: ${forcedWidth}px;` : undefined}
|
||||||
draggable={!isProtected}
|
draggable={!isProtected}
|
||||||
/>
|
/>
|
||||||
{hasThumb && !isPreviewPreloaded && (
|
{hasThumb && !isPreviewPreloaded && (
|
||||||
<canvas
|
<canvas ref={thumbRef} className="thumbnail" />
|
||||||
ref={thumbRef}
|
|
||||||
className={buildClassName('thumbnail', thumbClassNames)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{isProtected && <span className="protector" />}
|
{isProtected && <span className="protector" />}
|
||||||
<i className={buildClassName('icon', 'icon-large-play', playButtonClassNames)} />
|
<i ref={playButtonRef} className="icon icon-large-play" />
|
||||||
<MediaSpoiler
|
<MediaSpoiler
|
||||||
isVisible={isSpoilerShown}
|
isVisible={isSpoilerShown}
|
||||||
withAnimation
|
withAnimation
|
||||||
@ -276,7 +277,7 @@ const Video = <T,>({
|
|||||||
className="media-spoiler"
|
className="media-spoiler"
|
||||||
/>
|
/>
|
||||||
{shouldRenderSpinner && (
|
{shouldRenderSpinner && (
|
||||||
<div className={buildClassName('media-loading', spinnerClassNames)}>
|
<div ref={spinnerRef} className="media-loading">
|
||||||
<ProgressSpinner
|
<ProgressSpinner
|
||||||
progress={transferProgress}
|
progress={transferProgress}
|
||||||
onClick={handleClickOnSpinner}
|
onClick={handleClickOnSpinner}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import { disableDirectTextInput, enableDirectTextInput } from '../../util/direct
|
|||||||
import freezeWhenClosed from '../../util/hoc/freezeWhenClosed';
|
import freezeWhenClosed from '../../util/hoc/freezeWhenClosed';
|
||||||
import trapFocus from '../../util/trapFocus';
|
import trapFocus from '../../util/trapFocus';
|
||||||
|
|
||||||
import useDerivedState from '../../hooks/useDerivedState';
|
|
||||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
@ -66,12 +65,12 @@ const Modal: FC<OwnProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
ref: modalRef,
|
ref: modalRef,
|
||||||
getShouldRender,
|
shouldRender,
|
||||||
} = useShowTransition({
|
} = useShowTransition({
|
||||||
isOpen,
|
isOpen,
|
||||||
onCloseAnimationEnd,
|
onCloseAnimationEnd,
|
||||||
|
withShouldRender: true,
|
||||||
});
|
});
|
||||||
const shouldRender = useDerivedState(getShouldRender);
|
|
||||||
|
|
||||||
const withCloseButton = hasCloseButton || hasAbsoluteCloseButton;
|
const withCloseButton = hasCloseButton || hasAbsoluteCloseButton;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
import React, { useRef } from '../../lib/teact/teact';
|
import React, { useRef } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import useDerivedState from '../../hooks/useDerivedState';
|
|
||||||
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
|
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
|
||||||
import useShowTransition from '../../hooks/useShowTransition';
|
import useShowTransition from '../../hooks/useShowTransition';
|
||||||
|
|
||||||
@ -37,14 +36,14 @@ const ShowTransition: FC<OwnProps> = ({
|
|||||||
const fromChildrenRef = useRef<React.ReactNode>();
|
const fromChildrenRef = useRef<React.ReactNode>();
|
||||||
const isFirstRender = prevIsOpen === undefined;
|
const isFirstRender = prevIsOpen === undefined;
|
||||||
|
|
||||||
const { ref, getShouldRender } = useShowTransition({
|
const { ref, shouldRender } = useShowTransition({
|
||||||
isOpen: isOpen && !isHidden,
|
isOpen: isOpen && !isHidden,
|
||||||
ref: externalRef,
|
ref: externalRef,
|
||||||
noMountTransition: isFirstRender && !shouldAnimateFirstRender,
|
noMountTransition: isFirstRender && !shouldAnimateFirstRender,
|
||||||
className: isCustom ? false : undefined,
|
className: isCustom ? false : undefined,
|
||||||
noCloseTransition,
|
noCloseTransition,
|
||||||
|
withShouldRender: true,
|
||||||
});
|
});
|
||||||
const shouldRender = useDerivedState(getShouldRender);
|
|
||||||
|
|
||||||
if (prevIsOpen && !isOpen) {
|
if (prevIsOpen && !isOpen) {
|
||||||
fromChildrenRef.current = prevChildren;
|
fromChildrenRef.current = prevChildren;
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useLayoutEffect, useRef, useSignal } from '../lib/teact/teact';
|
|||||||
import { addExtraClass, toggleExtraClass } from '../lib/teact/teact-dom';
|
import { addExtraClass, toggleExtraClass } from '../lib/teact/teact-dom';
|
||||||
|
|
||||||
import { requestMeasure } from '../lib/fasterdom/fasterdom';
|
import { requestMeasure } from '../lib/fasterdom/fasterdom';
|
||||||
import useDerivedSignal from './useDerivedSignal';
|
import useDerivedState from './useDerivedState';
|
||||||
import useLastCallback from './useLastCallback';
|
import useLastCallback from './useLastCallback';
|
||||||
import { useStateRef } from './useStateRef';
|
import { useStateRef } from './useStateRef';
|
||||||
import useSyncEffectWithPrevDeps from './useSyncEffectWithPrevDeps';
|
import useSyncEffectWithPrevDeps from './useSyncEffectWithPrevDeps';
|
||||||
@ -26,6 +26,7 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
|
|||||||
className = 'fast',
|
className = 'fast',
|
||||||
prefix = '',
|
prefix = '',
|
||||||
onCloseAnimationEnd,
|
onCloseAnimationEnd,
|
||||||
|
withShouldRender,
|
||||||
}: {
|
}: {
|
||||||
isOpen: boolean | undefined;
|
isOpen: boolean | undefined;
|
||||||
ref?: RefObject<RefType>;
|
ref?: RefObject<RefType>;
|
||||||
@ -35,6 +36,7 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
|
|||||||
closeDuration?: number;
|
closeDuration?: number;
|
||||||
className?: string | false;
|
className?: string | false;
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
|
withShouldRender?: boolean;
|
||||||
onCloseAnimationEnd?: NoneToVoidFunction;
|
onCloseAnimationEnd?: NoneToVoidFunction;
|
||||||
}) {
|
}) {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// 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);
|
toggleExtraClass(element, `${prefix}closing`, isClosing);
|
||||||
}, [className, getState, prefix, ref]);
|
}, [className, getState, prefix, ref]);
|
||||||
|
|
||||||
const getShouldRender = useDerivedSignal(() => getState() !== 'closed', [getState]);
|
const shouldRender = useDerivedState(
|
||||||
|
() => (withShouldRender && getState() !== 'closed'),
|
||||||
|
[withShouldRender, getState],
|
||||||
|
);
|
||||||
|
|
||||||
return { ref, getShouldRender };
|
return { ref, shouldRender };
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user