TelegramPWA/src/components/common/MediaSpoiler.tsx
zubiden 9857dc0ec7 Chat: Fix restriction validation (#6078)
Co-authored-by: Dmitry Kabanov <dmitrykabanovdev@gmail.com>
2025-07-29 14:33:49 +02:00

89 lines
2.4 KiB
TypeScript

import type { FC } from '../../lib/teact/teact';
import type React from '../../lib/teact/teact';
import { memo, useRef } from '../../lib/teact/teact';
import { requestMutation } from '../../lib/fasterdom/fasterdom';
import buildClassName from '../../util/buildClassName';
import useCanvasBlur from '../../hooks/useCanvasBlur';
import useLang from '../../hooks/useLang';
import useLastCallback from '../../hooks/useLastCallback';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import Icon from './icons/Icon';
import styles from './MediaSpoiler.module.scss';
type OwnProps = {
isVisible: boolean;
withAnimation?: boolean;
thumbDataUri?: string;
isNsfw?: boolean;
width?: number;
height?: number;
className?: string;
};
const BLUR_RADIUS = 25;
const ANIMATION_DURATION = 500;
const MediaSpoiler: FC<OwnProps> = ({
isVisible,
withAnimation,
thumbDataUri,
isNsfw,
className,
width,
height,
}) => {
const ref = useRef<HTMLDivElement>();
const lang = useLang();
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(
isVisible, undefined, true, withAnimation ? false : undefined, undefined, ANIMATION_DURATION,
);
const canvasRef = useCanvasBlur(thumbDataUri, !shouldRender, undefined, BLUR_RADIUS, width, height);
const handleClick = useLastCallback((e: React.MouseEvent<HTMLDivElement>) => {
if (!ref.current) return;
const el = ref.current;
const rect = e.currentTarget.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const shiftX = x - (rect.width / 2);
const shiftY = y - (rect.height / 2);
requestMutation(() => {
el.setAttribute('style', `--click-shift-x: ${shiftX}px; --click-shift-y: ${shiftY}px`);
});
});
if (!shouldRender) {
return undefined;
}
return (
<div
className={buildClassName(styles.root, transitionClassNames, className, withAnimation && styles.maskAnimation)}
ref={ref}
onClick={withAnimation ? handleClick : undefined}
>
<canvas
ref={canvasRef}
className={styles.canvas}
width={width}
height={height}
/>
<div className={styles.dots} />
{isNsfw && (
<span className={styles.nsfw}>
<Icon name="eye-crossed-outline" className={styles.nsfwIcon} />
{lang('MediaSpoilerSensitive')}
</span>
)}
</div>
);
};
export default memo(MediaSpoiler);