fix crash on image with no data
This commit is contained in:
+16
-4
@@ -349,15 +349,21 @@ function quoteImage(data) {
|
|||||||
// Get the blob from the image data.
|
// Get the blob from the image data.
|
||||||
if (data.val) {
|
if (data.val) {
|
||||||
const blob = base64ToBlob(data.val, data.mime);
|
const blob = base64ToBlob(data.val, data.mime);
|
||||||
promise = blob ? Promise.resolve(blob) : Promise.reject(new Error("Invalid image"));
|
if (!blob) {
|
||||||
} else {
|
throw new Error("Invalid image");
|
||||||
promise = fetch(this.authorizeURL(sanitizeImageUrl(data.ref))).then(evt => {
|
}
|
||||||
|
promise = Promise.resolve(blob);
|
||||||
|
} else if (data.ref) {
|
||||||
|
promise = fetch(this.authorizeURL(sanitizeImageUrl(data.ref)))
|
||||||
|
.then(evt => {
|
||||||
if (evt.ok) {
|
if (evt.ok) {
|
||||||
return evt.blob();
|
return evt.blob();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Image fetch unsuccessful: ${evt.status} ${evt.statusText}`);
|
throw new Error(`Image fetch unsuccessful: ${evt.status} ${evt.statusText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error("Missing image data");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale the blob.
|
// Scale the blob.
|
||||||
@@ -392,7 +398,13 @@ function quoteImage(data) {
|
|||||||
export function replyFormatter(style, data, values, key, stack) {
|
export function replyFormatter(style, data, values, key, stack) {
|
||||||
if (style == 'IM') {
|
if (style == 'IM') {
|
||||||
const attr = inlineImageAttr.call(this, {key: key}, data);
|
const attr = inlineImageAttr.call(this, {key: key}, data);
|
||||||
attr.whenDone = cancelablePromise(quoteImage.call(this, data));
|
let loadedPromise;
|
||||||
|
try {
|
||||||
|
loadedPromise = cancelablePromise(quoteImage.call(this, data));
|
||||||
|
} catch (error) {
|
||||||
|
loadedPromise = cancelablePromise(error);
|
||||||
|
}
|
||||||
|
attr.whenDone = loadedPromise;
|
||||||
values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];
|
values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];
|
||||||
return React.createElement(React.Fragment, {key: key}, values);
|
return React.createElement(React.Fragment, {key: key}, values);
|
||||||
} else if (style == 'QQ') {
|
} else if (style == 'QQ') {
|
||||||
|
|||||||
+6
-2
@@ -183,10 +183,14 @@ export function deliveryMarker(received) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wraps a promise to make it cancelable.
|
// Wraps a promise to make it cancelable.
|
||||||
|
// The parameter can be either a promise or an error. If it's an error, the wrapped promise is
|
||||||
|
// created in a rejected state.
|
||||||
export function cancelablePromise(promise) {
|
export function cancelablePromise(promise) {
|
||||||
let hasCanceled = false;
|
let hasCanceled = false;
|
||||||
|
|
||||||
const wrappedPromise = new Promise((resolve, reject) => {
|
const wrappedPromise = promise instanceof Error ?
|
||||||
|
Promise.reject(promise) :
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
promise.then(
|
promise.then(
|
||||||
result => hasCanceled ? reject({isCanceled: true}) : resolve(result),
|
result => hasCanceled ? reject({isCanceled: true}) : resolve(result),
|
||||||
error => hasCanceled ? reject({isCanceled: true}) : reject(error)
|
error => hasCanceled ? reject({isCanceled: true}) : reject(error)
|
||||||
@@ -195,7 +199,7 @@ export function cancelablePromise(promise) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
promise: wrappedPromise,
|
promise: wrappedPromise,
|
||||||
cancel( ) {
|
cancel() {
|
||||||
hasCanceled = true;
|
hasCanceled = true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default class ImagePreview extends React.PureComponent {
|
|||||||
<div id="image-preview">
|
<div id="image-preview">
|
||||||
<div id="image-preview-caption-panel">
|
<div id="image-preview-caption-panel">
|
||||||
{!this.props.onSendMessage ?
|
{!this.props.onSendMessage ?
|
||||||
<a href={this.props.content.url} download={this.props.content.name}>
|
<a href={this.props.content.url} download={true}>
|
||||||
<i className="material-icons">file_download</i> <FormattedMessage
|
<i className="material-icons">file_download</i> <FormattedMessage
|
||||||
id="download_action" defaultMessage="download" description="Call to action [download]" />
|
id="download_action" defaultMessage="download" description="Call to action [download]" />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export default class LazyImage extends React.PureComponent {
|
|||||||
if (prevProps.whenDone != this.props.whenDone) {
|
if (prevProps.whenDone != this.props.whenDone) {
|
||||||
this.setState({src: 'img/placeholder.png', style: {...this.state.style, padding: '4px'}});
|
this.setState({src: 'img/placeholder.png', style: {...this.state.style, padding: '4px'}});
|
||||||
this.props.whenDone
|
this.props.whenDone
|
||||||
|
.promise
|
||||||
.then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))
|
.then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))
|
||||||
.catch(() => this.setState({src: 'img/broken_image.png'}));
|
.catch(() => this.setState({src: 'img/broken_image.png'}));
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-6
@@ -787,8 +787,13 @@ function quoteImage(data) {
|
|||||||
|
|
||||||
if (data.val) {
|
if (data.val) {
|
||||||
const blob = (0,_blob_helpers_js__WEBPACK_IMPORTED_MODULE_6__.base64ToBlob)(data.val, data.mime);
|
const blob = (0,_blob_helpers_js__WEBPACK_IMPORTED_MODULE_6__.base64ToBlob)(data.val, data.mime);
|
||||||
promise = blob ? Promise.resolve(blob) : Promise.reject(new Error("Invalid image"));
|
|
||||||
} else {
|
if (!blob) {
|
||||||
|
throw new Error("Invalid image");
|
||||||
|
}
|
||||||
|
|
||||||
|
promise = Promise.resolve(blob);
|
||||||
|
} else if (data.ref) {
|
||||||
promise = fetch(this.authorizeURL((0,_utils_js__WEBPACK_IMPORTED_MODULE_8__.sanitizeImageUrl)(data.ref))).then(evt => {
|
promise = fetch(this.authorizeURL((0,_utils_js__WEBPACK_IMPORTED_MODULE_8__.sanitizeImageUrl)(data.ref))).then(evt => {
|
||||||
if (evt.ok) {
|
if (evt.ok) {
|
||||||
return evt.blob();
|
return evt.blob();
|
||||||
@@ -796,6 +801,8 @@ function quoteImage(data) {
|
|||||||
throw new Error("Image fetch unsuccessful: ".concat(evt.status, " ").concat(evt.statusText));
|
throw new Error("Image fetch unsuccessful: ".concat(evt.status, " ").concat(evt.statusText));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error("Missing image data");
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(blob => {
|
return promise.then(blob => {
|
||||||
@@ -825,7 +832,15 @@ function replyFormatter(style, data, values, key, stack) {
|
|||||||
const attr = inlineImageAttr.call(this, {
|
const attr = inlineImageAttr.call(this, {
|
||||||
key: key
|
key: key
|
||||||
}, data);
|
}, data);
|
||||||
attr.whenDone = (0,_utils_js__WEBPACK_IMPORTED_MODULE_8__.cancelablePromise)(quoteImage.call(this, data));
|
let loadedPromise;
|
||||||
|
|
||||||
|
try {
|
||||||
|
loadedPromise = (0,_utils_js__WEBPACK_IMPORTED_MODULE_8__.cancelablePromise)(quoteImage.call(this, data));
|
||||||
|
} catch (error) {
|
||||||
|
loadedPromise = (0,_utils_js__WEBPACK_IMPORTED_MODULE_8__.cancelablePromise)(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.whenDone = loadedPromise;
|
||||||
values = [react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_lazy_image_jsx__WEBPACK_IMPORTED_MODULE_3__["default"], attr, null), ' ', attr.alt];
|
values = [react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_lazy_image_jsx__WEBPACK_IMPORTED_MODULE_3__["default"], attr, null), ' ', attr.alt];
|
||||||
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), {
|
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), {
|
||||||
key: key
|
key: key
|
||||||
@@ -1312,7 +1327,7 @@ function deliveryMarker(received) {
|
|||||||
}
|
}
|
||||||
function cancelablePromise(promise) {
|
function cancelablePromise(promise) {
|
||||||
let hasCanceled = false;
|
let hasCanceled = false;
|
||||||
const wrappedPromise = new Promise((resolve, reject) => {
|
const wrappedPromise = promise instanceof Error ? Promise.reject(promise) : new Promise((resolve, reject) => {
|
||||||
promise.then(result => hasCanceled ? reject({
|
promise.then(result => hasCanceled ? reject({
|
||||||
isCanceled: true
|
isCanceled: true
|
||||||
}) : resolve(result), error => hasCanceled ? reject({
|
}) : resolve(result), error => hasCanceled ? reject({
|
||||||
@@ -10331,7 +10346,7 @@ class ImagePreview extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
|
|||||||
id: "image-preview-caption-panel"
|
id: "image-preview-caption-panel"
|
||||||
}, !this.props.onSendMessage ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
|
}, !this.props.onSendMessage ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
|
||||||
href: this.props.content.url,
|
href: this.props.content.url,
|
||||||
download: this.props.content.name
|
download: true
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
|
||||||
className: "material-icons"
|
className: "material-icons"
|
||||||
}, "file_download"), " ", react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
}, "file_download"), " ", react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||||
@@ -10684,7 +10699,7 @@ class LazyImage extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
|
|||||||
padding: '4px'
|
padding: '4px'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.props.whenDone.then(data => this.setState({
|
this.props.whenDone.promise.then(data => this.setState({
|
||||||
src: data.src,
|
src: data.src,
|
||||||
style: { ...this.state.style,
|
style: { ...this.state.style,
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user