Merge pull request #1967 from matrix-org/luke/fix-crash-on-unspecified-thumbnail-info

Fix crash on unspecified thumbnail info, and handle gracefully
This commit is contained in:
David Baker 2018-06-14 16:10:35 +01:00 committed by GitHub
commit a3bc68c562
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -65,6 +65,7 @@ export default class extends React.Component {
error: null, error: null,
imgError: false, imgError: false,
imgLoaded: false, imgLoaded: false,
loadedImageDimensions: null,
hover: false, hover: false,
}; };
} }
@ -147,7 +148,16 @@ export default class extends React.Component {
onImageLoad() { onImageLoad() {
this.props.onWidgetLoad(); this.props.onWidgetLoad();
this.setState({ imgLoaded: true });
let loadedImageDimensions;
if (this.refs.image) {
const { naturalWidth, naturalHeight } = this.refs.image;
loadedImageDimensions = { naturalWidth, naturalHeight };
}
this.setState({ imgLoaded: true, loadedImageDimensions });
} }
_getContentUrl() { _getContentUrl() {
@ -185,7 +195,7 @@ export default class extends React.Component {
const content = this.props.mxEvent.getContent(); const content = this.props.mxEvent.getContent();
if (content.file !== undefined && this.state.decryptedUrl === null) { if (content.file !== undefined && this.state.decryptedUrl === null) {
let thumbnailPromise = Promise.resolve(null); let thumbnailPromise = Promise.resolve(null);
if (content.info.thumbnail_file) { if (content.info && content.info.thumbnail_file) {
thumbnailPromise = decryptFile( thumbnailPromise = decryptFile(
content.info.thumbnail_file, content.info.thumbnail_file,
).then(function(blob) { ).then(function(blob) {
@ -239,11 +249,37 @@ export default class extends React.Component {
} }
_messageContent(contentUrl, thumbUrl, content) { _messageContent(contentUrl, thumbUrl, content) {
let infoWidth;
let infoHeight;
if (content && content.info && content.info.w && content.info.h) {
infoWidth = content.info.w;
infoHeight = content.info.h;
} else {
// Whilst the image loads, display nothing.
//
// Once loaded, use the loaded image dimensions stored in `loadedImageDimensions`.
//
// By doing this, the image "pops" into the timeline, but is still restricted
// by the same width and height logic below.
if (!this.state.loadedImageDimensions) {
return this.wrapImage(contentUrl,
<img style={{display: 'none'}} src={thumbUrl} ref="image"
alt={content.body}
onError={this.onImageError}
onLoad={this.onImageLoad}
/>,
);
}
infoWidth = this.state.loadedImageDimensions.naturalWidth;
infoHeight = this.state.loadedImageDimensions.naturalHeight;
}
// The maximum height of the thumbnail as it is rendered as an <img> // The maximum height of the thumbnail as it is rendered as an <img>
const maxHeight = Math.min(this.props.maxImageHeight || 600, content.info.h); const maxHeight = Math.min(this.props.maxImageHeight || 600, infoHeight);
// The maximum width of the thumbnail, as dictated by its natural // The maximum width of the thumbnail, as dictated by its natural
// maximum height. // maximum height.
const maxWidth = content.info.w * maxHeight / content.info.h; const maxWidth = infoWidth * maxHeight / infoHeight;
let img = null; let img = null;
let placeholder = null; let placeholder = null;
@ -274,12 +310,12 @@ export default class extends React.Component {
const thumbnail = ( const thumbnail = (
<div className="mx_MImageBody_thumbnail_container" style={{ "max-height": maxHeight + "px" }} > <div className="mx_MImageBody_thumbnail_container" style={{ "max-height": maxHeight + "px" }} >
{ /* Calculate aspect ratio, using %padding will size _container correctly */ } { /* Calculate aspect ratio, using %padding will size _container correctly */ }
<div style={{ paddingBottom: (100 * content.info.h / content.info.w) + '%' }}></div> <div style={{ paddingBottom: (100 * infoHeight / infoWidth) + '%' }}></div>
{ showPlaceholder && { showPlaceholder &&
<div className="mx_MImageBody_thumbnail" style={{ <div className="mx_MImageBody_thumbnail" style={{
// Constrain width here so that spinner appears central to the loaded thumbnail // Constrain width here so that spinner appears central to the loaded thumbnail
"max-width": content.info.w + "px", "max-width": infoWidth + "px",
}}> }}>
<div className="mx_MImageBody_thumbnail_spinner"> <div className="mx_MImageBody_thumbnail_spinner">
{ placeholder } { placeholder }