Add a renderImage
directive which handles errors
This commit is contained in:
parent
8943609d10
commit
a014eca9e7
@ -318,9 +318,9 @@ describe("XEP-0363: HTTP File Upload", function () {
|
|||||||
`</message>`);
|
`</message>`);
|
||||||
await u.waitUntil(() => view.el.querySelector('.chat-image'), 1000);
|
await u.waitUntil(() => view.el.querySelector('.chat-image'), 1000);
|
||||||
// Check that the image renders
|
// Check that the image renders
|
||||||
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual(
|
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.replace(/<!---->/g, '').trim()).toEqual(
|
||||||
`<!----><a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
`<a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
||||||
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a><!---->`);
|
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a>`);
|
||||||
XMLHttpRequest.prototype.send = send_backup;
|
XMLHttpRequest.prototype.send = send_backup;
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -422,9 +422,9 @@ describe("XEP-0363: HTTP File Upload", function () {
|
|||||||
`</message>`);
|
`</message>`);
|
||||||
await u.waitUntil(() => view.el.querySelector('.chat-image'), 1000);
|
await u.waitUntil(() => view.el.querySelector('.chat-image'), 1000);
|
||||||
// Check that the image renders
|
// Check that the image renders
|
||||||
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual(
|
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.replace(/<!---->/g, '').trim()).toEqual(
|
||||||
`<!----><a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
`<a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
||||||
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a><!---->`);
|
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a>`);
|
||||||
|
|
||||||
XMLHttpRequest.prototype.send = send_backup;
|
XMLHttpRequest.prototype.send = send_backup;
|
||||||
done();
|
done();
|
||||||
|
@ -952,7 +952,7 @@ describe("A Chat Message", function () {
|
|||||||
let msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
|
let msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
|
||||||
expect(msg.innerHTML.replace(/<!---->/g, '').trim()).toEqual(
|
expect(msg.innerHTML.replace(/<!---->/g, '').trim()).toEqual(
|
||||||
`<a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
`<a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
||||||
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg">`+
|
`<img class="chat-image img-thumbnail" src="https://conversejs.org/logo/conversejs-filled.svg">`+
|
||||||
`</a>`);
|
`</a>`);
|
||||||
|
|
||||||
message += "?param1=val1¶m2=val2";
|
message += "?param1=val1¶m2=val2";
|
||||||
@ -982,6 +982,27 @@ describe("A Chat Message", function () {
|
|||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("will fall back to rendering images as URLs",
|
||||||
|
mock.initConverse(
|
||||||
|
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
await mock.waitForRoster(_converse, 'current');
|
||||||
|
const base_url = 'https://conversejs.org';
|
||||||
|
const message = base_url+"/logo/non-existing.svg";
|
||||||
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||||
|
await mock.openChatBoxFor(_converse, contact_jid);
|
||||||
|
const view = _converse.api.chatviews.get(contact_jid);
|
||||||
|
spyOn(view.model, 'sendMessage').and.callThrough();
|
||||||
|
mock.sendMessage(view, message);
|
||||||
|
await u.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length, 1000)
|
||||||
|
expect(view.model.sendMessage).toHaveBeenCalled();
|
||||||
|
const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
|
||||||
|
await u.waitUntil(() => msg.innerHTML.replace(/<!---->/g, '').trim() ==
|
||||||
|
`<a target="_blank" rel="noopener" href="https://conversejs.org/logo/non-existing.svg">https://conversejs.org/logo/non-existing.svg</a>`);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
|
||||||
it("will render the message time as configured",
|
it("will render the message time as configured",
|
||||||
mock.initConverse(
|
mock.initConverse(
|
||||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||||
@ -1971,9 +1992,9 @@ describe("A Chat Message", function () {
|
|||||||
expect(u.hasClass('chat-msg__text', msg)).toBe(true);
|
expect(u.hasClass('chat-msg__text', msg)).toBe(true);
|
||||||
expect(msg.textContent).toEqual('Have you seen this funny image?');
|
expect(msg.textContent).toEqual('Have you seen this funny image?');
|
||||||
const media = view.el.querySelector('.chat-msg .chat-msg__media');
|
const media = view.el.querySelector('.chat-msg .chat-msg__media');
|
||||||
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
|
expect(media.innerHTML.replace(/<!---->/g, '').replace(/(\r\n|\n|\r)/gm, "")).toEqual(
|
||||||
`<!----><a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
`<a class="chat-image__link" target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg">`+
|
||||||
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a><!---->`);
|
`<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg"></a>`);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -206,9 +206,8 @@ class MessageBodyRenderer {
|
|||||||
|
|
||||||
|
|
||||||
export const renderBodyText = directive(component => part => {
|
export const renderBodyText = directive(component => part => {
|
||||||
const model = component.model;
|
|
||||||
const renderer = new MessageBodyRenderer(component);
|
const renderer = new MessageBodyRenderer(component);
|
||||||
part.setValue(renderer.render());
|
part.setValue(renderer.render());
|
||||||
part.commit();
|
const model = component.model;
|
||||||
model.collection?.trigger('rendered', model);
|
model.collection?.trigger('rendered', model);
|
||||||
});
|
});
|
||||||
|
16
src/templates/directives/image.js
Normal file
16
src/templates/directives/image.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { directive, html } from "lit-html";
|
||||||
|
|
||||||
|
|
||||||
|
export const renderImage = directive(url => part => {
|
||||||
|
function onError () {
|
||||||
|
part.setValue(converse.env.utils.convertUrlToHyperlink(url));
|
||||||
|
part.commit();
|
||||||
|
}
|
||||||
|
part.setValue(
|
||||||
|
html`<a href="${url}"
|
||||||
|
class="chat-image__link"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
><img class="chat-image img-thumbnail" src="${url}" @error=${onError}/></a>`
|
||||||
|
);
|
||||||
|
});
|
@ -1,3 +1,4 @@
|
|||||||
import { html } from "lit-html";
|
import { html } from "lit-html";
|
||||||
|
import { renderImage } from "./directives/image.js";
|
||||||
|
|
||||||
export default (o) => html`<a href="${o.url}" class="chat-image__link" target="_blank" rel="noopener"><img class="chat-image img-thumbnail" src="${o.url}"/></a>`;
|
export default (o) => html`${renderImage(o.url)}`;
|
||||||
|
@ -99,11 +99,7 @@ function renderImageURL (_converse, uri) {
|
|||||||
if (!_converse.api.settings.get('show_images_inline')) {
|
if (!_converse.api.settings.get('show_images_inline')) {
|
||||||
return u.convertURIoHyperlink(uri);
|
return u.convertURIoHyperlink(uri);
|
||||||
}
|
}
|
||||||
const { __ } = _converse;
|
return tpl_image({'url': uri.toString()});
|
||||||
return tpl_image({
|
|
||||||
'url': uri.toString(),
|
|
||||||
'label_download': __('Download image "%1$s"', getFileName(uri))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFileURL (_converse, uri) {
|
function renderFileURL (_converse, uri) {
|
||||||
@ -162,24 +158,6 @@ u.applyDragResistance = function (value, default_value) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function loadImage (url) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const err_msg = `Could not determine whether it's an image: ${url}`;
|
|
||||||
const img = new Image();
|
|
||||||
const timer = window.setTimeout(() => reject(new Error(err_msg)), 20000);
|
|
||||||
img.onerror = img.onabort = function () {
|
|
||||||
clearTimeout(timer);
|
|
||||||
reject(new Error(err_msg));
|
|
||||||
};
|
|
||||||
img.onload = function () {
|
|
||||||
clearTimeout(timer);
|
|
||||||
resolve(img);
|
|
||||||
};
|
|
||||||
img.src = url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u.calculateElementHeight = function (el) {
|
u.calculateElementHeight = function (el) {
|
||||||
/* Return the height of the passed in DOM element,
|
/* Return the height of the passed in DOM element,
|
||||||
* based on the heights of its children.
|
* based on the heights of its children.
|
||||||
@ -311,24 +289,17 @@ u.escapeHTML = function (string) {
|
|||||||
.replace(/"/g, """);
|
.replace(/"/g, """);
|
||||||
};
|
};
|
||||||
|
|
||||||
u.convertToImageTag = async function (url) {
|
|
||||||
|
u.convertToImageTag = function (url) {
|
||||||
const uri = getURI(url);
|
const uri = getURI(url);
|
||||||
const img_url_without_ext = ['imgur.com', 'pbs.twimg.com'].includes(uri.hostname());
|
const img_url_without_ext = ['imgur.com', 'pbs.twimg.com'].includes(uri.hostname());
|
||||||
let src;
|
|
||||||
if (u.isImageURL(url) || img_url_without_ext) {
|
if (u.isImageURL(url) || img_url_without_ext) {
|
||||||
if (img_url_without_ext) {
|
if (img_url_without_ext) {
|
||||||
const format = (uri.hostname() === 'pbs.twimg.com') ? uri.search(true).format : 'png';
|
const format = (uri.hostname() === 'pbs.twimg.com') ? uri.search(true).format : 'png';
|
||||||
src = uri.removeSearch(/.*/).toString() + `.${format}`;
|
return tpl_image({'url': uri.removeSearch(/.*/).toString() + `.${format}`});
|
||||||
} else {
|
} else {
|
||||||
src = url;
|
return tpl_image({url});
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await loadImage(src);
|
|
||||||
} catch (e) {
|
|
||||||
log.error(e);
|
|
||||||
return u.convertUrlToHyperlink(url);
|
|
||||||
}
|
|
||||||
return tpl_image({url, src});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user