mirror of
https://github.com/danog/telegram-tt.git
synced 2024-12-02 09:37:47 +01:00
Revert "[Perf] Use canvas for faster blur (#1100)"
This reverts commit 27cc33b5541e6f9fe27cf74220e8629a5966d339.
This commit is contained in:
parent
3e15d53c2f
commit
e1cf508eca
@ -20,16 +20,12 @@
|
||||
grid-column-end: span 2;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
.preview {
|
||||
background-size: cover !important;
|
||||
background: transparent no-repeat center;
|
||||
}
|
||||
|
||||
.thumbnail ~ video {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.thumbnail, video {
|
||||
.preview, video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
|
@ -8,9 +8,9 @@ import buildClassName from '../../util/buildClassName';
|
||||
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
||||
import useMedia from '../../hooks/useMedia';
|
||||
import useTransitionForMedia from '../../hooks/useTransitionForMedia';
|
||||
import useBlur from '../../hooks/useBlur';
|
||||
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
||||
import useBuffering from '../../hooks/useBuffering';
|
||||
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
||||
|
||||
import Spinner from '../ui/Spinner';
|
||||
|
||||
@ -31,15 +31,15 @@ const GifButton: FC<OwnProps> = ({
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
const hasThumbnail = gif.thumbnail && !!gif.thumbnail.dataUri;
|
||||
const localMediaHash = `gif${gif.id}`;
|
||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||
const loadAndPlay = isIntersecting && !isDisabled;
|
||||
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !loadAndPlay, ApiMediaFormat.BlobUrl);
|
||||
const thumbRef = useCanvasBlur(gif.thumbnail && gif.thumbnail.dataUri, Boolean(previewBlobUrl));
|
||||
const thumbDataUri = useBlur(gif.thumbnail && gif.thumbnail.dataUri, Boolean(previewBlobUrl));
|
||||
const previewData = previewBlobUrl || thumbDataUri;
|
||||
const videoData = useMedia(localMediaHash, !loadAndPlay, ApiMediaFormat.BlobUrl);
|
||||
const shouldRenderVideo = Boolean(loadAndPlay && videoData);
|
||||
const { transitionClassNames } = useTransitionForMedia(hasThumbnail || previewBlobUrl || videoData, 'slow');
|
||||
const { transitionClassNames } = useTransitionForMedia(previewData || videoData, 'slow');
|
||||
const { isBuffered, bufferingHandlers } = useBuffering(true);
|
||||
const shouldRenderSpinner = loadAndPlay && !isBuffered;
|
||||
|
||||
@ -66,20 +66,14 @@ const GifButton: FC<OwnProps> = ({
|
||||
className={className}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{hasThumbnail && (
|
||||
<canvas
|
||||
ref={thumbRef}
|
||||
className="thumbnail"
|
||||
{previewData && !shouldRenderVideo && (
|
||||
<div
|
||||
className="preview"
|
||||
// @ts-ignore
|
||||
style={`background-image: url(${previewData});`}
|
||||
/>
|
||||
)}
|
||||
{!hasThumbnail && previewBlobUrl && (
|
||||
<img
|
||||
src={previewBlobUrl}
|
||||
alt=""
|
||||
className="thumbnail"
|
||||
/>
|
||||
)}
|
||||
{(shouldRenderVideo || previewBlobUrl) && (
|
||||
{shouldRenderVideo && (
|
||||
<video
|
||||
ref={videoRef}
|
||||
autoPlay
|
||||
@ -87,6 +81,7 @@ const GifButton: FC<OwnProps> = ({
|
||||
muted
|
||||
playsInline
|
||||
preload="none"
|
||||
poster={previewData}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...bufferingHandlers}
|
||||
>
|
||||
@ -94,7 +89,7 @@ const GifButton: FC<OwnProps> = ({
|
||||
</video>
|
||||
)}
|
||||
{shouldRenderSpinner && (
|
||||
<Spinner color={previewBlobUrl || hasThumbnail ? 'white' : 'black'} />
|
||||
<Spinner color={previewData ? 'white' : 'black'} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -18,7 +18,7 @@
|
||||
transform: scale(1);
|
||||
transition: transform .15s ease;
|
||||
|
||||
img, canvas {
|
||||
img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
@ -13,7 +13,7 @@ import useMedia from '../../../hooks/useMedia';
|
||||
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
||||
import useShowTransition from '../../../hooks/useShowTransition';
|
||||
import usePrevious from '../../../hooks/usePrevious';
|
||||
import useCanvasBlur from '../../../hooks/useCanvasBlur';
|
||||
import useBlur from '../../../hooks/useBlur';
|
||||
|
||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||
|
||||
@ -25,6 +25,8 @@ type OwnProps = {
|
||||
onClick: (slug: string) => void;
|
||||
};
|
||||
|
||||
const ANIMATION_DURATION = 300;
|
||||
|
||||
const WallpaperTile: FC<OwnProps> = ({
|
||||
wallpaper,
|
||||
isSelected,
|
||||
@ -35,10 +37,10 @@ const WallpaperTile: FC<OwnProps> = ({
|
||||
const localMediaHash = `wallpaper${document.id!}`;
|
||||
const localBlobUrl = document.previewBlobUrl;
|
||||
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
|
||||
const thumbRef = useCanvasBlur(
|
||||
const thumbDataUri = useBlur(
|
||||
document.thumbnail && document.thumbnail.dataUri,
|
||||
Boolean(previewBlobUrl),
|
||||
true,
|
||||
ANIMATION_DURATION,
|
||||
);
|
||||
const {
|
||||
shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,
|
||||
@ -86,9 +88,10 @@ const WallpaperTile: FC<OwnProps> = ({
|
||||
<div className={className} onClick={handleClick}>
|
||||
<div className="media-inner">
|
||||
{shouldRenderThumb && (
|
||||
<canvas
|
||||
ref={thumbRef}
|
||||
<img
|
||||
src={thumbDataUri}
|
||||
className="thumbnail"
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{shouldRenderFullMedia && (
|
||||
|
@ -16,8 +16,8 @@ import { ObserveFn, useIsIntersecting } from '../../../hooks/useIntersectionObse
|
||||
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
||||
import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
||||
import useShowTransition from '../../../hooks/useShowTransition';
|
||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||
import usePrevious from '../../../hooks/usePrevious';
|
||||
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
||||
@ -69,7 +69,7 @@ const Photo: FC<OwnProps> = ({
|
||||
mediaData, downloadProgress,
|
||||
} = useMediaWithDownloadProgress(getMessageMediaHash(message, size), !shouldDownload);
|
||||
const fullMediaData = localBlobUrl || mediaData;
|
||||
const thumbRef = useBlurredMediaThumbRef(message, fullMediaData);
|
||||
const thumbDataUri = useBlurredMediaThumb(message, fullMediaData);
|
||||
|
||||
const {
|
||||
isUploading, isTransferring, transferProgress,
|
||||
@ -122,6 +122,11 @@ const Photo: FC<OwnProps> = ({
|
||||
width === height && 'square-image',
|
||||
);
|
||||
|
||||
const thumbClassName = buildClassName(
|
||||
'thumbnail',
|
||||
!thumbDataUri && 'empty',
|
||||
);
|
||||
|
||||
const style = dimensions
|
||||
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;`
|
||||
: '';
|
||||
@ -136,11 +141,12 @@ const Photo: FC<OwnProps> = ({
|
||||
onClick={isUploading ? undefined : handleClick}
|
||||
>
|
||||
{shouldRenderThumb && (
|
||||
<canvas
|
||||
ref={thumbRef}
|
||||
className="thumbnail"
|
||||
// @ts-ignore teact feature
|
||||
style={`width: ${width}px; height: ${height}px`}
|
||||
<img
|
||||
src={thumbDataUri}
|
||||
className={thumbClassName}
|
||||
width={width}
|
||||
height={height}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{shouldRenderFullMedia && (
|
||||
|
@ -20,8 +20,8 @@ import useBuffering from '../../../hooks/useBuffering';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
||||
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
||||
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||
import safePlay from '../../../util/safePlay';
|
||||
|
||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||
@ -74,7 +74,7 @@ const RoundVideo: FC<OwnProps> = ({
|
||||
getMessageMediaFormat(message, 'inline'),
|
||||
lastSyncTime,
|
||||
);
|
||||
const thumbRef = useBlurredMediaThumbRef(message, mediaData);
|
||||
const thumbDataUri = useBlurredMediaThumb(message, mediaData);
|
||||
|
||||
const { isBuffered, bufferingHandlers } = useBuffering();
|
||||
const isTransferring = isDownloadAllowed && !isBuffered;
|
||||
@ -183,11 +183,12 @@ const RoundVideo: FC<OwnProps> = ({
|
||||
>
|
||||
{shouldRenderThumb && (
|
||||
<div className="thumbnail-wrapper">
|
||||
<canvas
|
||||
ref={thumbRef}
|
||||
<img
|
||||
src={thumbDataUri}
|
||||
className="thumbnail"
|
||||
// @ts-ignore teact feature
|
||||
style={`width: ${ROUND_VIDEO_DIMENSIONS}px; height: ${ROUND_VIDEO_DIMENSIONS}px`}
|
||||
width={ROUND_VIDEO_DIMENSIONS}
|
||||
height={ROUND_VIDEO_DIMENSIONS}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -203,6 +204,7 @@ const RoundVideo: FC<OwnProps> = ({
|
||||
muted={!isActivated}
|
||||
loop={!isActivated}
|
||||
playsInline
|
||||
poster={thumbDataUri}
|
||||
onEnded={isActivated ? stopPlaying : undefined}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...bufferingHandlers}
|
||||
|
@ -24,9 +24,9 @@ import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
||||
import usePrevious from '../../../hooks/usePrevious';
|
||||
import useBuffering from '../../../hooks/useBuffering';
|
||||
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
||||
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
||||
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||
|
||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||
|
||||
@ -76,7 +76,7 @@ const Video: FC<OwnProps> = ({
|
||||
getMessageMediaFormat(message, 'pictogram'),
|
||||
lastSyncTime,
|
||||
);
|
||||
const thumbRef = useBlurredMediaThumbRef(message);
|
||||
const thumbDataUri = useBlurredMediaThumb(message, previewBlobUrl);
|
||||
const { mediaData, downloadProgress } = useMediaWithDownloadProgress(
|
||||
getMessageMediaHash(message, 'inline'),
|
||||
!shouldDownload,
|
||||
@ -84,6 +84,7 @@ const Video: FC<OwnProps> = ({
|
||||
lastSyncTime,
|
||||
);
|
||||
|
||||
const previewMediaData = previewBlobUrl || thumbDataUri;
|
||||
const fullMediaData = localBlobUrl || mediaData;
|
||||
const isInline = Boolean(canPlayInline && isIntersecting && fullMediaData);
|
||||
|
||||
@ -131,10 +132,9 @@ const Video: FC<OwnProps> = ({
|
||||
}, [isUploading, canPlayInline, fullMediaData, isPlayAllowed, onClick, onCancelUpload, message]);
|
||||
|
||||
const className = buildClassName('media-inner dark', !isUploading && 'interactive');
|
||||
const thumbClassName = buildClassName('thumbnail', !previewMediaData && 'empty');
|
||||
const videoClassName = buildClassName('full-media', transitionClassNames);
|
||||
const videoStyle = previewBlobUrl
|
||||
? `background-image: url(${previewBlobUrl}); background-size: cover`
|
||||
: 'background: transparent';
|
||||
const videoStyle = previewMediaData ? `background-image: url(${previewMediaData}); background-size: cover` : '';
|
||||
|
||||
const style = dimensions
|
||||
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;`
|
||||
@ -154,25 +154,15 @@ const Video: FC<OwnProps> = ({
|
||||
style={style}
|
||||
onClick={isUploading ? undefined : handleClick}
|
||||
>
|
||||
{((!isInline || shouldRenderThumb) && !previewBlobUrl)
|
||||
&& (
|
||||
<canvas
|
||||
ref={thumbRef}
|
||||
className="thumbnail"
|
||||
// @ts-ignore teact feature
|
||||
style={`width: ${width}px; height: ${height}px;`}
|
||||
/>
|
||||
)}
|
||||
{previewBlobUrl && fullMediaData && (
|
||||
{(shouldRenderThumb || !isInline) && (
|
||||
<img
|
||||
src={previewBlobUrl}
|
||||
className="thumbnail"
|
||||
// @ts-ignore teact feature
|
||||
style={`width: ${width}px; height: ${height}px;`}
|
||||
src={previewMediaData}
|
||||
className={thumbClassName}
|
||||
width={width}
|
||||
height={height}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldRenderInlineVideo && (
|
||||
<video
|
||||
ref={videoRef}
|
||||
|
14
src/components/middle/message/hooks/useBlurredMediaThumb.ts
Normal file
14
src/components/middle/message/hooks/useBlurredMediaThumb.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ApiMessage } from '../../../../api/types';
|
||||
|
||||
import { LAYERS_TRANSITION_DURATION } from '../../../../config';
|
||||
import { IS_MOBILE_SCREEN } from '../../../../util/environment';
|
||||
import { getMessageMediaThumbDataUri } from '../../../../modules/helpers';
|
||||
import useBlur from '../../../../hooks/useBlur';
|
||||
|
||||
export default function useBlurredMediaThumb(message: ApiMessage, fullMediaData?: string) {
|
||||
return useBlur(
|
||||
getMessageMediaThumbDataUri(message),
|
||||
Boolean(fullMediaData),
|
||||
IS_MOBILE_SCREEN ? LAYERS_TRANSITION_DURATION : undefined,
|
||||
);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import { ApiMessage } from '../../../../api/types';
|
||||
|
||||
import { IS_CANVAS_FILTER_SUPPORTED, IS_MOBILE_SCREEN } from '../../../../util/environment';
|
||||
import { getMessageMediaThumbDataUri } from '../../../../modules/helpers';
|
||||
import useCanvasBlur from '../../../../hooks/useCanvasBlur';
|
||||
|
||||
export default function useBlurredMediaThumbRef(message: ApiMessage, fullMediaData?: string) {
|
||||
return useCanvasBlur(
|
||||
getMessageMediaThumbDataUri(message),
|
||||
Boolean(fullMediaData),
|
||||
IS_MOBILE_SCREEN && !IS_CANVAS_FILTER_SUPPORTED,
|
||||
);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
import { useEffect, useRef } from '../lib/teact/teact';
|
||||
|
||||
import fastBlur from '../lib/fastBlur';
|
||||
import useForceUpdate from './useForceUpdate';
|
||||
import { IS_CANVAS_FILTER_SUPPORTED } from '../util/environment';
|
||||
|
||||
const RADIUS = 2;
|
||||
const ITERATIONS = 2;
|
||||
|
||||
export default function useCanvasBlur(dataUri?: string, isDisabled = false, withRaf?: boolean) {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
|
||||
if (!dataUri || !canvas || isDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const img = new Image();
|
||||
|
||||
const processBlur = () => {
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
const ctx = canvas.getContext('2d', { alpha: false })!;
|
||||
|
||||
if (IS_CANVAS_FILTER_SUPPORTED) {
|
||||
ctx.filter = `blur(${RADIUS}px)`;
|
||||
}
|
||||
|
||||
ctx.drawImage(img, -RADIUS * 2, -RADIUS * 2, canvas.width + RADIUS * 4, canvas.height + RADIUS * 4);
|
||||
|
||||
if (!IS_CANVAS_FILTER_SUPPORTED) {
|
||||
fastBlur(ctx, 0, 0, canvas.width, canvas.height, RADIUS, ITERATIONS);
|
||||
}
|
||||
};
|
||||
|
||||
img.onload = () => {
|
||||
if (withRaf) {
|
||||
requestAnimationFrame(processBlur);
|
||||
} else {
|
||||
processBlur();
|
||||
}
|
||||
};
|
||||
|
||||
img.src = dataUri;
|
||||
}, [canvasRef, dataUri, forceUpdate, isDisabled, withRaf]);
|
||||
|
||||
return canvasRef;
|
||||
}
|
@ -19,6 +19,12 @@
|
||||
.thumbnail ~ .full-media, .media-loading {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
&.empty {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.animated-close-icon {
|
||||
|
@ -47,7 +47,6 @@ export const IS_SERVICE_WORKER_SUPPORTED = 'serviceWorker' in navigator;
|
||||
export const IS_PROGRESSIVE_SUPPORTED = IS_SERVICE_WORKER_SUPPORTED;
|
||||
export const IS_STREAMING_SUPPORTED = 'MediaSource' in window;
|
||||
export const IS_OPUS_SUPPORTED = Boolean((new Audio()).canPlayType('audio/ogg; codecs=opus'));
|
||||
export const IS_CANVAS_FILTER_SUPPORTED = 'filter' in (document.createElement('canvas').getContext('2d') || {});
|
||||
|
||||
export const DPR = window.devicePixelRatio || 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user