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;
|
grid-column-end: span 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail {
|
.preview {
|
||||||
background-size: cover !important;
|
background-size: cover !important;
|
||||||
background: transparent no-repeat center;
|
background: transparent no-repeat center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail ~ video {
|
.preview, video {
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thumbnail, video {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
|||||||
@ -8,9 +8,9 @@ import buildClassName from '../../util/buildClassName';
|
|||||||
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
||||||
import useMedia from '../../hooks/useMedia';
|
import useMedia from '../../hooks/useMedia';
|
||||||
import useTransitionForMedia from '../../hooks/useTransitionForMedia';
|
import useTransitionForMedia from '../../hooks/useTransitionForMedia';
|
||||||
|
import useBlur from '../../hooks/useBlur';
|
||||||
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
||||||
import useBuffering from '../../hooks/useBuffering';
|
import useBuffering from '../../hooks/useBuffering';
|
||||||
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
|
||||||
|
|
||||||
import Spinner from '../ui/Spinner';
|
import Spinner from '../ui/Spinner';
|
||||||
|
|
||||||
@ -31,15 +31,15 @@ const GifButton: FC<OwnProps> = ({
|
|||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const videoRef = useRef<HTMLVideoElement>(null);
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
|
|
||||||
const hasThumbnail = gif.thumbnail && !!gif.thumbnail.dataUri;
|
|
||||||
const localMediaHash = `gif${gif.id}`;
|
const localMediaHash = `gif${gif.id}`;
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
const loadAndPlay = isIntersecting && !isDisabled;
|
const loadAndPlay = isIntersecting && !isDisabled;
|
||||||
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !loadAndPlay, ApiMediaFormat.BlobUrl);
|
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 videoData = useMedia(localMediaHash, !loadAndPlay, ApiMediaFormat.BlobUrl);
|
||||||
const shouldRenderVideo = Boolean(loadAndPlay && videoData);
|
const shouldRenderVideo = Boolean(loadAndPlay && videoData);
|
||||||
const { transitionClassNames } = useTransitionForMedia(hasThumbnail || previewBlobUrl || videoData, 'slow');
|
const { transitionClassNames } = useTransitionForMedia(previewData || videoData, 'slow');
|
||||||
const { isBuffered, bufferingHandlers } = useBuffering(true);
|
const { isBuffered, bufferingHandlers } = useBuffering(true);
|
||||||
const shouldRenderSpinner = loadAndPlay && !isBuffered;
|
const shouldRenderSpinner = loadAndPlay && !isBuffered;
|
||||||
|
|
||||||
@ -66,20 +66,14 @@ const GifButton: FC<OwnProps> = ({
|
|||||||
className={className}
|
className={className}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
{hasThumbnail && (
|
{previewData && !shouldRenderVideo && (
|
||||||
<canvas
|
<div
|
||||||
ref={thumbRef}
|
className="preview"
|
||||||
className="thumbnail"
|
// @ts-ignore
|
||||||
|
style={`background-image: url(${previewData});`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!hasThumbnail && previewBlobUrl && (
|
{shouldRenderVideo && (
|
||||||
<img
|
|
||||||
src={previewBlobUrl}
|
|
||||||
alt=""
|
|
||||||
className="thumbnail"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{(shouldRenderVideo || previewBlobUrl) && (
|
|
||||||
<video
|
<video
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
autoPlay
|
autoPlay
|
||||||
@ -87,6 +81,7 @@ const GifButton: FC<OwnProps> = ({
|
|||||||
muted
|
muted
|
||||||
playsInline
|
playsInline
|
||||||
preload="none"
|
preload="none"
|
||||||
|
poster={previewData}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
{...bufferingHandlers}
|
{...bufferingHandlers}
|
||||||
>
|
>
|
||||||
@ -94,7 +89,7 @@ const GifButton: FC<OwnProps> = ({
|
|||||||
</video>
|
</video>
|
||||||
)}
|
)}
|
||||||
{shouldRenderSpinner && (
|
{shouldRenderSpinner && (
|
||||||
<Spinner color={previewBlobUrl || hasThumbnail ? 'white' : 'black'} />
|
<Spinner color={previewData ? 'white' : 'black'} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
transition: transform .15s ease;
|
transition: transform .15s ease;
|
||||||
|
|
||||||
img, canvas {
|
img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import useMedia from '../../../hooks/useMedia';
|
|||||||
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
||||||
import useShowTransition from '../../../hooks/useShowTransition';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
import useCanvasBlur from '../../../hooks/useCanvasBlur';
|
import useBlur from '../../../hooks/useBlur';
|
||||||
|
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
|
|
||||||
@ -25,6 +25,8 @@ type OwnProps = {
|
|||||||
onClick: (slug: string) => void;
|
onClick: (slug: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ANIMATION_DURATION = 300;
|
||||||
|
|
||||||
const WallpaperTile: FC<OwnProps> = ({
|
const WallpaperTile: FC<OwnProps> = ({
|
||||||
wallpaper,
|
wallpaper,
|
||||||
isSelected,
|
isSelected,
|
||||||
@ -35,10 +37,10 @@ const WallpaperTile: FC<OwnProps> = ({
|
|||||||
const localMediaHash = `wallpaper${document.id!}`;
|
const localMediaHash = `wallpaper${document.id!}`;
|
||||||
const localBlobUrl = document.previewBlobUrl;
|
const localBlobUrl = document.previewBlobUrl;
|
||||||
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
|
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
|
||||||
const thumbRef = useCanvasBlur(
|
const thumbDataUri = useBlur(
|
||||||
document.thumbnail && document.thumbnail.dataUri,
|
document.thumbnail && document.thumbnail.dataUri,
|
||||||
Boolean(previewBlobUrl),
|
Boolean(previewBlobUrl),
|
||||||
true,
|
ANIMATION_DURATION,
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,
|
shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,
|
||||||
@ -86,9 +88,10 @@ const WallpaperTile: FC<OwnProps> = ({
|
|||||||
<div className={className} onClick={handleClick}>
|
<div className={className} onClick={handleClick}>
|
||||||
<div className="media-inner">
|
<div className="media-inner">
|
||||||
{shouldRenderThumb && (
|
{shouldRenderThumb && (
|
||||||
<canvas
|
<img
|
||||||
ref={thumbRef}
|
src={thumbDataUri}
|
||||||
className="thumbnail"
|
className="thumbnail"
|
||||||
|
alt=""
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{shouldRenderFullMedia && (
|
{shouldRenderFullMedia && (
|
||||||
|
|||||||
@ -16,8 +16,8 @@ import { ObserveFn, useIsIntersecting } from '../../../hooks/useIntersectionObse
|
|||||||
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
import useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';
|
||||||
import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
||||||
import useShowTransition from '../../../hooks/useShowTransition';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
|
||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
|
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
||||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
||||||
@ -69,7 +69,7 @@ const Photo: FC<OwnProps> = ({
|
|||||||
mediaData, downloadProgress,
|
mediaData, downloadProgress,
|
||||||
} = useMediaWithDownloadProgress(getMessageMediaHash(message, size), !shouldDownload);
|
} = useMediaWithDownloadProgress(getMessageMediaHash(message, size), !shouldDownload);
|
||||||
const fullMediaData = localBlobUrl || mediaData;
|
const fullMediaData = localBlobUrl || mediaData;
|
||||||
const thumbRef = useBlurredMediaThumbRef(message, fullMediaData);
|
const thumbDataUri = useBlurredMediaThumb(message, fullMediaData);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isUploading, isTransferring, transferProgress,
|
isUploading, isTransferring, transferProgress,
|
||||||
@ -122,6 +122,11 @@ const Photo: FC<OwnProps> = ({
|
|||||||
width === height && 'square-image',
|
width === height && 'square-image',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const thumbClassName = buildClassName(
|
||||||
|
'thumbnail',
|
||||||
|
!thumbDataUri && 'empty',
|
||||||
|
);
|
||||||
|
|
||||||
const style = dimensions
|
const style = dimensions
|
||||||
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;`
|
? `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}
|
onClick={isUploading ? undefined : handleClick}
|
||||||
>
|
>
|
||||||
{shouldRenderThumb && (
|
{shouldRenderThumb && (
|
||||||
<canvas
|
<img
|
||||||
ref={thumbRef}
|
src={thumbDataUri}
|
||||||
className="thumbnail"
|
className={thumbClassName}
|
||||||
// @ts-ignore teact feature
|
width={width}
|
||||||
style={`width: ${width}px; height: ${height}px`}
|
height={height}
|
||||||
|
alt=""
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{shouldRenderFullMedia && (
|
{shouldRenderFullMedia && (
|
||||||
|
|||||||
@ -20,8 +20,8 @@ import useBuffering from '../../../hooks/useBuffering';
|
|||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
||||||
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
||||||
|
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||||
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
|
||||||
import safePlay from '../../../util/safePlay';
|
import safePlay from '../../../util/safePlay';
|
||||||
|
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
@ -74,7 +74,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
getMessageMediaFormat(message, 'inline'),
|
getMessageMediaFormat(message, 'inline'),
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
);
|
);
|
||||||
const thumbRef = useBlurredMediaThumbRef(message, mediaData);
|
const thumbDataUri = useBlurredMediaThumb(message, mediaData);
|
||||||
|
|
||||||
const { isBuffered, bufferingHandlers } = useBuffering();
|
const { isBuffered, bufferingHandlers } = useBuffering();
|
||||||
const isTransferring = isDownloadAllowed && !isBuffered;
|
const isTransferring = isDownloadAllowed && !isBuffered;
|
||||||
@ -183,11 +183,12 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
>
|
>
|
||||||
{shouldRenderThumb && (
|
{shouldRenderThumb && (
|
||||||
<div className="thumbnail-wrapper">
|
<div className="thumbnail-wrapper">
|
||||||
<canvas
|
<img
|
||||||
ref={thumbRef}
|
src={thumbDataUri}
|
||||||
className="thumbnail"
|
className="thumbnail"
|
||||||
// @ts-ignore teact feature
|
width={ROUND_VIDEO_DIMENSIONS}
|
||||||
style={`width: ${ROUND_VIDEO_DIMENSIONS}px; height: ${ROUND_VIDEO_DIMENSIONS}px`}
|
height={ROUND_VIDEO_DIMENSIONS}
|
||||||
|
alt=""
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -203,6 +204,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
muted={!isActivated}
|
muted={!isActivated}
|
||||||
loop={!isActivated}
|
loop={!isActivated}
|
||||||
playsInline
|
playsInline
|
||||||
|
poster={thumbDataUri}
|
||||||
onEnded={isActivated ? stopPlaying : undefined}
|
onEnded={isActivated ? stopPlaying : undefined}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
{...bufferingHandlers}
|
{...bufferingHandlers}
|
||||||
|
|||||||
@ -24,9 +24,9 @@ import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
|||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
import useBuffering from '../../../hooks/useBuffering';
|
import useBuffering from '../../../hooks/useBuffering';
|
||||||
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
||||||
|
import useBlurredMediaThumb from './hooks/useBlurredMediaThumb';
|
||||||
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
||||||
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
|
||||||
|
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
getMessageMediaFormat(message, 'pictogram'),
|
getMessageMediaFormat(message, 'pictogram'),
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
);
|
);
|
||||||
const thumbRef = useBlurredMediaThumbRef(message);
|
const thumbDataUri = useBlurredMediaThumb(message, previewBlobUrl);
|
||||||
const { mediaData, downloadProgress } = useMediaWithDownloadProgress(
|
const { mediaData, downloadProgress } = useMediaWithDownloadProgress(
|
||||||
getMessageMediaHash(message, 'inline'),
|
getMessageMediaHash(message, 'inline'),
|
||||||
!shouldDownload,
|
!shouldDownload,
|
||||||
@ -84,6 +84,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const previewMediaData = previewBlobUrl || thumbDataUri;
|
||||||
const fullMediaData = localBlobUrl || mediaData;
|
const fullMediaData = localBlobUrl || mediaData;
|
||||||
const isInline = Boolean(canPlayInline && isIntersecting && fullMediaData);
|
const isInline = Boolean(canPlayInline && isIntersecting && fullMediaData);
|
||||||
|
|
||||||
@ -131,10 +132,9 @@ const Video: FC<OwnProps> = ({
|
|||||||
}, [isUploading, canPlayInline, fullMediaData, isPlayAllowed, onClick, onCancelUpload, message]);
|
}, [isUploading, canPlayInline, fullMediaData, isPlayAllowed, onClick, onCancelUpload, message]);
|
||||||
|
|
||||||
const className = buildClassName('media-inner dark', !isUploading && 'interactive');
|
const className = buildClassName('media-inner dark', !isUploading && 'interactive');
|
||||||
|
const thumbClassName = buildClassName('thumbnail', !previewMediaData && 'empty');
|
||||||
const videoClassName = buildClassName('full-media', transitionClassNames);
|
const videoClassName = buildClassName('full-media', transitionClassNames);
|
||||||
const videoStyle = previewBlobUrl
|
const videoStyle = previewMediaData ? `background-image: url(${previewMediaData}); background-size: cover` : '';
|
||||||
? `background-image: url(${previewBlobUrl}); background-size: cover`
|
|
||||||
: 'background: transparent';
|
|
||||||
|
|
||||||
const style = dimensions
|
const style = dimensions
|
||||||
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;`
|
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;`
|
||||||
@ -154,25 +154,15 @@ const Video: FC<OwnProps> = ({
|
|||||||
style={style}
|
style={style}
|
||||||
onClick={isUploading ? undefined : handleClick}
|
onClick={isUploading ? undefined : handleClick}
|
||||||
>
|
>
|
||||||
{((!isInline || shouldRenderThumb) && !previewBlobUrl)
|
{(shouldRenderThumb || !isInline) && (
|
||||||
&& (
|
|
||||||
<canvas
|
|
||||||
ref={thumbRef}
|
|
||||||
className="thumbnail"
|
|
||||||
// @ts-ignore teact feature
|
|
||||||
style={`width: ${width}px; height: ${height}px;`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{previewBlobUrl && fullMediaData && (
|
|
||||||
<img
|
<img
|
||||||
src={previewBlobUrl}
|
src={previewMediaData}
|
||||||
className="thumbnail"
|
className={thumbClassName}
|
||||||
// @ts-ignore teact feature
|
width={width}
|
||||||
style={`width: ${width}px; height: ${height}px;`}
|
height={height}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{shouldRenderInlineVideo && (
|
{shouldRenderInlineVideo && (
|
||||||
<video
|
<video
|
||||||
ref={videoRef}
|
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 {
|
.thumbnail ~ .full-media, .media-loading {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
&.empty {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.animated-close-icon {
|
.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_PROGRESSIVE_SUPPORTED = IS_SERVICE_WORKER_SUPPORTED;
|
||||||
export const IS_STREAMING_SUPPORTED = 'MediaSource' in window;
|
export const IS_STREAMING_SUPPORTED = 'MediaSource' in window;
|
||||||
export const IS_OPUS_SUPPORTED = Boolean((new Audio()).canPlayType('audio/ogg; codecs=opus'));
|
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;
|
export const DPR = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user