GIF attachments

This commit is contained in:
Fedor Indutny 2021-04-27 15:11:59 -07:00 committed by Scott Nonnenberg
parent 5f17d01f49
commit caf1d4c4da
15 changed files with 526 additions and 93 deletions

View file

@ -14,6 +14,7 @@ import { Spinner } from '../Spinner';
import { MessageBody } from './MessageBody';
import { ExpireTimer } from './ExpireTimer';
import { ImageGrid } from './ImageGrid';
import { GIF } from './GIF';
import { Image } from './Image';
import { Timestamp } from './Timestamp';
import { ContactName } from './ContactName';
@ -42,6 +43,7 @@ import {
isImage,
isImageAttachment,
isVideo,
isGIF,
} from '../../types/Attachment';
import { ContactType } from '../../types/Contact';
@ -58,6 +60,7 @@ type Trigger = {
};
const STICKER_SIZE = 200;
const GIF_SIZE = 300;
const SELECTED_TIMEOUT = 1000;
const THREE_HOURS = 3 * 60 * 60 * 1000;
@ -116,6 +119,7 @@ export type PropsData = {
| 'profileName'
| 'title'
>;
reducedMotion?: boolean;
conversationType: ConversationTypesType;
attachments?: Array<AttachmentType>;
quote?: {
@ -696,6 +700,7 @@ export class Message extends React.Component<Props, State> {
isSticker,
text,
theme,
reducedMotion,
renderAudioAttachment,
} = this.props;
@ -714,52 +719,72 @@ export class Message extends React.Component<Props, State> {
(conversationType === 'group' && direction === 'incoming');
const displayImage = canDisplayImage(attachments);
if (
displayImage &&
!imageBroken &&
(isImage(attachments) || isVideo(attachments))
) {
if (displayImage && !imageBroken) {
const prefix = isSticker ? 'sticker' : 'attachment';
const bottomOverlay = !isSticker && !collapseMetadata;
// We only want users to tab into this if there's more than one
const tabIndex = attachments.length > 1 ? 0 : -1;
return (
<div
className={classNames(
`module-message__${prefix}-container`,
withContentAbove
? `module-message__${prefix}-container--with-content-above`
: null,
withContentBelow
? 'module-message__attachment-container--with-content-below'
: null,
isSticker && !collapseMetadata
? 'module-message__sticker-container--with-content-below'
: null
)}
>
<ImageGrid
attachments={attachments}
withContentAbove={isSticker || withContentAbove}
withContentBelow={isSticker || withContentBelow}
isSticker={isSticker}
stickerSize={STICKER_SIZE}
bottomOverlay={bottomOverlay}
i18n={i18n}
theme={theme}
onError={this.handleImageError}
tabIndex={tabIndex}
onClick={attachment => {
if (hasNotDownloaded(attachment)) {
kickOffAttachmentDownload({ attachment, messageId: id });
} else {
showVisualAttachment({ attachment, messageId: id });
}
}}
/>
</div>
const containerClassName = classNames(
`module-message__${prefix}-container`,
withContentAbove
? `module-message__${prefix}-container--with-content-above`
: null,
withContentBelow
? 'module-message__attachment-container--with-content-below'
: null,
isSticker && !collapseMetadata
? 'module-message__sticker-container--with-content-below'
: null
);
if (isGIF(attachments)) {
return (
<div className={containerClassName}>
<GIF
attachment={firstAttachment}
size={GIF_SIZE}
theme={theme}
i18n={i18n}
tabIndex={0}
reducedMotion={reducedMotion}
onError={this.handleImageError}
kickOffAttachmentDownload={() => {
kickOffAttachmentDownload({
attachment: firstAttachment,
messageId: id,
});
}}
/>
</div>
);
}
if (isImage(attachments) || isVideo(attachments)) {
const bottomOverlay = !isSticker && !collapseMetadata;
// We only want users to tab into this if there's more than one
const tabIndex = attachments.length > 1 ? 0 : -1;
return (
<div className={containerClassName}>
<ImageGrid
attachments={attachments}
withContentAbove={isSticker || withContentAbove}
withContentBelow={isSticker || withContentBelow}
isSticker={isSticker}
stickerSize={STICKER_SIZE}
bottomOverlay={bottomOverlay}
i18n={i18n}
theme={theme}
onError={this.handleImageError}
tabIndex={tabIndex}
onClick={attachment => {
if (hasNotDownloaded(attachment)) {
kickOffAttachmentDownload({ attachment, messageId: id });
} else {
showVisualAttachment({ attachment, messageId: id });
}
}}
/>
</div>
);
}
}
if (isAudio(attachments)) {
return renderAudioAttachment({
@ -1553,6 +1578,11 @@ export class Message extends React.Component<Props, State> {
const { attachments, isSticker, previews } = this.props;
if (attachments && attachments.length) {
if (isGIF(attachments)) {
// Message container border + image border
return GIF_SIZE + 4;
}
if (isSticker) {
// Padding is 8px, on both sides, plus two for 1px border
return STICKER_SIZE + 8 * 2 + 2;
@ -2009,6 +2039,11 @@ export class Message extends React.Component<Props, State> {
const isAttachmentPending = this.isAttachmentPending();
// Don't show lightbox for GIFs
if (isGIF(attachments)) {
return;
}
if (isTapToView) {
if (isAttachmentPending) {
return;
@ -2186,6 +2221,7 @@ export class Message extends React.Component<Props, State> {
public renderContainer(): JSX.Element {
const {
attachments,
author,
deletedForEveryone,
direction,
@ -2203,6 +2239,7 @@ export class Message extends React.Component<Props, State> {
const containerClassnames = classNames(
'module-message__container',
isGIF(attachments) ? 'module-message__container--gif' : null,
isSelected && !isSticker ? 'module-message__container--selected' : null,
isSticker ? 'module-message__container--with-sticker' : null,
!isSticker ? `module-message__container--${direction}` : null,