// Copyright 2018-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React from 'react'; import classNames from 'classnames'; import { Blurhash } from 'react-blurhash'; import { Spinner } from '../Spinner'; import { LocalizerType } from '../../types/Util'; import { AttachmentType } from '../../types/Attachment'; export interface Props { alt: string; attachment: AttachmentType; url: string; height?: number; width?: number; tabIndex?: number; overlayText?: string; noBorder?: boolean; noBackground?: boolean; bottomOverlay?: boolean; closeButton?: boolean; curveBottomLeft?: boolean; curveBottomRight?: boolean; curveTopLeft?: boolean; curveTopRight?: boolean; smallCurveTopLeft?: boolean; darkOverlay?: boolean; playIconOverlay?: boolean; softCorners?: boolean; blurHash?: string; i18n: LocalizerType; onClick?: (attachment: AttachmentType) => void; onClickClose?: (attachment: AttachmentType) => void; onError?: () => void; } export class Image extends React.Component { private canClick() { const { onClick, attachment, url } = this.props; const { pending } = attachment || { pending: true }; return Boolean(onClick && !pending && url); } public handleClick = (event: React.MouseEvent): void => { if (!this.canClick()) { event.preventDefault(); event.stopPropagation(); return; } const { onClick, attachment } = this.props; if (onClick) { event.preventDefault(); event.stopPropagation(); onClick(attachment); } }; public handleKeyDown = ( event: React.KeyboardEvent ): void => { if (!this.canClick()) { event.preventDefault(); event.stopPropagation(); return; } const { onClick, attachment } = this.props; if (onClick && (event.key === 'Enter' || event.key === 'Space')) { event.preventDefault(); event.stopPropagation(); onClick(attachment); } }; public render(): JSX.Element { const { alt, attachment, blurHash, bottomOverlay, closeButton, curveBottomLeft, curveBottomRight, curveTopLeft, curveTopRight, darkOverlay, height = 0, i18n, noBackground, noBorder, onClickClose, onError, overlayText, playIconOverlay, smallCurveTopLeft, softCorners, tabIndex, url, width = 0, } = this.props; const { caption, pending } = attachment || { caption: null, pending: true }; const canClick = this.canClick(); const overlayClassName = classNames( 'module-image__border-overlay', noBorder ? null : 'module-image__border-overlay--with-border', canClick ? 'module-image__border-overlay--with-click-handler' : null, curveTopLeft ? 'module-image--curved-top-left' : null, curveTopRight ? 'module-image--curved-top-right' : null, curveBottomLeft ? 'module-image--curved-bottom-left' : null, curveBottomRight ? 'module-image--curved-bottom-right' : null, smallCurveTopLeft ? 'module-image--small-curved-top-left' : null, softCorners ? 'module-image--soft-corners' : null, darkOverlay ? 'module-image__border-overlay--dark' : null ); const overlay = canClick ? ( // Not sure what this button does. // eslint-disable-next-line jsx-a11y/control-has-associated-label