Don't let quote thumbnails get taller than the quote itself

This commit is contained in:
Evan Hahn 2021-01-21 17:57:07 -06:00 committed by Scott Nonnenberg
parent ca669a2638
commit 932e44e3bf
3 changed files with 81 additions and 31 deletions

View file

@ -1,7 +1,8 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import React, { useRef, useState, useEffect, ReactNode } from 'react';
import { noop } from 'lodash';
import classNames from 'classnames';
import * as MIME from '../../types/MIME';
@ -132,11 +133,7 @@ export class Quote extends React.Component<Props, State> {
});
};
public renderImage(
url: string,
i18n: LocalizerType,
icon?: string
): JSX.Element {
public renderImage(url: string, icon?: string): JSX.Element {
const iconElement = icon ? (
<div className="module-quote__icon-container__inner">
<div className="module-quote__icon-container__circle-background">
@ -151,14 +148,9 @@ export class Quote extends React.Component<Props, State> {
) : null;
return (
<div className="module-quote__icon-container">
<img
src={url}
alt={i18n('quoteThumbnailAlt')}
onError={this.handleImageError}
/>
<ThumbnailImage src={url} onError={this.handleImageError}>
{iconElement}
</div>
</ThumbnailImage>
);
}
@ -213,7 +205,7 @@ export class Quote extends React.Component<Props, State> {
}
public renderIconContainer(): JSX.Element | null {
const { attachment, i18n } = this.props;
const { attachment } = this.props;
const { imageBroken } = this.state;
if (!attachment) {
@ -225,12 +217,12 @@ export class Quote extends React.Component<Props, State> {
if (GoogleChrome.isVideoTypeSupported(contentType)) {
return objectUrl && !imageBroken
? this.renderImage(objectUrl, i18n, 'play')
? this.renderImage(objectUrl, 'play')
: this.renderIcon('movie');
}
if (GoogleChrome.isImageTypeSupported(contentType)) {
return objectUrl && !imageBroken
? this.renderImage(objectUrl, i18n)
? this.renderImage(objectUrl)
: this.renderIcon('image');
}
if (MIME.isAudio(contentType)) {
@ -441,3 +433,51 @@ export class Quote extends React.Component<Props, State> {
);
}
}
function ThumbnailImage({
src,
onError,
children,
}: Readonly<{
src: string;
onError: () => void;
children: ReactNode;
}>): JSX.Element {
const imageRef = useRef(new Image());
const [loadedSrc, setLoadedSrc] = useState<null | string>(null);
useEffect(() => {
const image = new Image();
image.onload = () => {
setLoadedSrc(src);
};
image.src = src;
imageRef.current = image;
return () => {
image.onload = noop;
};
}, [src]);
useEffect(() => {
setLoadedSrc(null);
}, [src]);
useEffect(() => {
const image = imageRef.current;
image.onerror = onError;
return () => {
image.onerror = noop;
};
}, [onError]);
return (
<div
className="module-quote__icon-container"
style={
loadedSrc ? { backgroundImage: `url('${escape(loadedSrc)}')` } : {}
}
>
{children}
</div>
);
}