2018-11-14 18:47:19 +00:00
|
|
|
import React from 'react';
|
|
|
|
import classNames from 'classnames';
|
2020-05-27 21:37:06 +00:00
|
|
|
import { Blurhash } from 'react-blurhash';
|
2018-11-14 18:47:19 +00:00
|
|
|
|
2019-01-30 20:15:07 +00:00
|
|
|
import { Spinner } from '../Spinner';
|
2019-01-14 21:49:58 +00:00
|
|
|
import { LocalizerType } from '../../types/Util';
|
|
|
|
import { AttachmentType } from '../../types/Attachment';
|
2018-11-14 18:47:19 +00:00
|
|
|
|
2020-08-26 18:06:48 +00:00
|
|
|
export interface Props {
|
2018-11-14 18:47:19 +00:00
|
|
|
alt: string;
|
|
|
|
attachment: AttachmentType;
|
|
|
|
url: string;
|
|
|
|
|
|
|
|
height?: number;
|
|
|
|
width?: number;
|
2019-11-07 21:36:16 +00:00
|
|
|
tabIndex?: number;
|
2018-11-14 18:47:19 +00:00
|
|
|
|
|
|
|
overlayText?: string;
|
|
|
|
|
2019-05-16 22:32:11 +00:00
|
|
|
noBorder?: boolean;
|
|
|
|
noBackground?: boolean;
|
2018-11-14 18:47:19 +00:00
|
|
|
bottomOverlay?: boolean;
|
2018-12-02 01:48:53 +00:00
|
|
|
closeButton?: boolean;
|
2018-11-14 18:47:19 +00:00
|
|
|
curveBottomLeft?: boolean;
|
|
|
|
curveBottomRight?: boolean;
|
|
|
|
curveTopLeft?: boolean;
|
|
|
|
curveTopRight?: boolean;
|
2019-01-16 03:03:56 +00:00
|
|
|
|
|
|
|
smallCurveTopLeft?: boolean;
|
|
|
|
|
2018-11-14 18:47:19 +00:00
|
|
|
darkOverlay?: boolean;
|
|
|
|
playIconOverlay?: boolean;
|
2018-12-02 01:48:53 +00:00
|
|
|
softCorners?: boolean;
|
2020-05-27 21:37:06 +00:00
|
|
|
blurHash?: string;
|
2018-11-14 18:47:19 +00:00
|
|
|
|
2019-01-14 21:49:58 +00:00
|
|
|
i18n: LocalizerType;
|
2018-11-14 18:47:19 +00:00
|
|
|
onClick?: (attachment: AttachmentType) => void;
|
2018-12-02 01:48:53 +00:00
|
|
|
onClickClose?: (attachment: AttachmentType) => void;
|
2018-11-14 18:47:19 +00:00
|
|
|
onError?: () => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Image extends React.Component<Props> {
|
2020-05-27 21:37:06 +00:00
|
|
|
private canClick() {
|
|
|
|
const { onClick, attachment, url } = this.props;
|
|
|
|
const { pending } = attachment || { pending: true };
|
|
|
|
|
|
|
|
return Boolean(onClick && !pending && url);
|
|
|
|
}
|
|
|
|
|
2019-11-07 21:36:16 +00:00
|
|
|
public handleClick = (event: React.MouseEvent) => {
|
2020-05-27 21:37:06 +00:00
|
|
|
if (!this.canClick()) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-07 21:36:16 +00:00
|
|
|
const { onClick, attachment } = this.props;
|
|
|
|
|
|
|
|
if (onClick) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
|
|
onClick(attachment);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {
|
2020-05-27 21:37:06 +00:00
|
|
|
if (!this.canClick()) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-07 21:36:16 +00:00
|
|
|
const { onClick, attachment } = this.props;
|
|
|
|
|
|
|
|
if (onClick && (event.key === 'Enter' || event.key === 'Space')) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
onClick(attachment);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-12-02 01:48:53 +00:00
|
|
|
// tslint:disable-next-line max-func-body-length cyclomatic-complexity
|
2018-11-14 18:47:19 +00:00
|
|
|
public render() {
|
|
|
|
const {
|
|
|
|
alt,
|
|
|
|
attachment,
|
2020-05-27 21:37:06 +00:00
|
|
|
blurHash,
|
2018-11-14 18:47:19 +00:00
|
|
|
bottomOverlay,
|
2018-12-02 01:48:53 +00:00
|
|
|
closeButton,
|
2018-11-14 18:47:19 +00:00
|
|
|
curveBottomLeft,
|
|
|
|
curveBottomRight,
|
|
|
|
curveTopLeft,
|
|
|
|
curveTopRight,
|
|
|
|
darkOverlay,
|
2020-05-27 21:37:06 +00:00
|
|
|
height = 0,
|
2018-11-14 18:47:19 +00:00
|
|
|
i18n,
|
2019-05-16 22:32:11 +00:00
|
|
|
noBackground,
|
|
|
|
noBorder,
|
2018-12-02 01:48:53 +00:00
|
|
|
onClickClose,
|
2018-11-14 18:47:19 +00:00
|
|
|
onError,
|
|
|
|
overlayText,
|
|
|
|
playIconOverlay,
|
2019-01-16 03:03:56 +00:00
|
|
|
smallCurveTopLeft,
|
2018-12-02 01:48:53 +00:00
|
|
|
softCorners,
|
2019-11-07 21:36:16 +00:00
|
|
|
tabIndex,
|
2018-11-14 18:47:19 +00:00
|
|
|
url,
|
2020-05-27 21:37:06 +00:00
|
|
|
width = 0,
|
2018-11-14 18:47:19 +00:00
|
|
|
} = this.props;
|
|
|
|
|
2019-01-30 20:15:07 +00:00
|
|
|
const { caption, pending } = attachment || { caption: null, pending: true };
|
2020-05-27 21:37:06 +00:00
|
|
|
const canClick = this.canClick();
|
2019-11-07 21:36:16 +00:00
|
|
|
|
|
|
|
const overlayClassName = classNames(
|
|
|
|
'module-image__border-overlay',
|
|
|
|
noBorder ? null : 'module-image__border-overlay--with-border',
|
2020-05-27 21:37:06 +00:00
|
|
|
canClick ? 'module-image__border-overlay--with-click-handler' : null,
|
2019-11-07 21:36:16 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
|
2020-05-27 21:37:06 +00:00
|
|
|
const overlay = canClick ? (
|
|
|
|
<button
|
|
|
|
className={overlayClassName}
|
|
|
|
onClick={this.handleClick}
|
|
|
|
onKeyDown={this.handleKeyDown}
|
|
|
|
tabIndex={tabIndex}
|
|
|
|
/>
|
|
|
|
) : null;
|
2018-11-14 18:47:19 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
'module-image',
|
2019-05-16 22:32:11 +00:00
|
|
|
!noBackground ? 'module-image--with-background' : null,
|
2018-11-14 18:47:19 +00:00
|
|
|
curveBottomLeft ? 'module-image--curved-bottom-left' : null,
|
|
|
|
curveBottomRight ? 'module-image--curved-bottom-right' : null,
|
|
|
|
curveTopLeft ? 'module-image--curved-top-left' : null,
|
2018-12-02 01:48:53 +00:00
|
|
|
curveTopRight ? 'module-image--curved-top-right' : null,
|
2019-01-16 03:03:56 +00:00
|
|
|
smallCurveTopLeft ? 'module-image--small-curved-top-left' : null,
|
2018-12-02 01:48:53 +00:00
|
|
|
softCorners ? 'module-image--soft-corners' : null
|
2018-11-14 18:47:19 +00:00
|
|
|
)}
|
|
|
|
>
|
2019-01-30 20:15:07 +00:00
|
|
|
{pending ? (
|
|
|
|
<div
|
|
|
|
className="module-image__loading-placeholder"
|
|
|
|
style={{
|
|
|
|
height: `${height}px`,
|
|
|
|
width: `${width}px`,
|
|
|
|
lineHeight: `${height}px`,
|
|
|
|
textAlign: 'center',
|
|
|
|
}}
|
2019-11-07 21:36:16 +00:00
|
|
|
title={i18n('loading')}
|
2019-01-30 20:15:07 +00:00
|
|
|
>
|
2019-06-26 19:33:13 +00:00
|
|
|
<Spinner svgSize="normal" />
|
2019-01-30 20:15:07 +00:00
|
|
|
</div>
|
2020-05-27 21:37:06 +00:00
|
|
|
) : url ? (
|
2019-01-30 20:15:07 +00:00
|
|
|
<img
|
|
|
|
onError={onError}
|
|
|
|
className="module-image__image"
|
|
|
|
alt={alt}
|
|
|
|
height={height}
|
|
|
|
width={width}
|
|
|
|
src={url}
|
|
|
|
/>
|
2020-05-27 21:37:06 +00:00
|
|
|
) : blurHash ? (
|
|
|
|
<Blurhash
|
|
|
|
hash={blurHash}
|
|
|
|
width={width}
|
|
|
|
height={height}
|
|
|
|
style={{ display: 'block' }}
|
|
|
|
/>
|
|
|
|
) : null}
|
2018-11-14 18:47:19 +00:00
|
|
|
{caption ? (
|
|
|
|
<img
|
|
|
|
className="module-image__caption-icon"
|
|
|
|
src="images/caption-shadow.svg"
|
|
|
|
alt={i18n('imageCaptionIconAlt')}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
{bottomOverlay ? (
|
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
'module-image__bottom-overlay',
|
|
|
|
curveBottomLeft ? 'module-image--curved-bottom-left' : null,
|
|
|
|
curveBottomRight ? 'module-image--curved-bottom-right' : null
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
) : null}
|
2019-01-30 20:15:07 +00:00
|
|
|
{!pending && playIconOverlay ? (
|
2018-11-14 18:47:19 +00:00
|
|
|
<div className="module-image__play-overlay__circle">
|
|
|
|
<div className="module-image__play-overlay__icon" />
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{overlayText ? (
|
|
|
|
<div
|
|
|
|
className="module-image__text-container"
|
|
|
|
style={{ lineHeight: `${height}px` }}
|
|
|
|
>
|
|
|
|
{overlayText}
|
|
|
|
</div>
|
|
|
|
) : null}
|
2019-11-19 23:03:00 +00:00
|
|
|
{overlay}
|
2019-12-03 20:02:50 +00:00
|
|
|
{closeButton ? (
|
|
|
|
<button
|
|
|
|
onClick={(e: React.MouseEvent<{}>) => {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
if (onClickClose) {
|
|
|
|
onClickClose(attachment);
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
className="module-image__close-button"
|
|
|
|
title={i18n('remove-attachment')}
|
|
|
|
/>
|
|
|
|
) : null}
|
2018-11-14 18:47:19 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|