message-view: Re-use image element and fix autoscroll after image loads

This commit is contained in:
JC Brand 2020-01-21 15:06:51 +01:00
parent 685c9585f4
commit 901f70272e
3 changed files with 28 additions and 21 deletions

View File

@ -1000,18 +1000,15 @@
expect(view.model.sendMessage).toHaveBeenCalled();
let msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
expect(msg.innerHTML.trim()).toEqual(
'<!-- src/templates/image.html -->\n'+
'<a href="'+base_url+'/logo/conversejs-filled.svg" target="_blank" rel="noopener"><img class="chat-image img-thumbnail"'+
' src="' + message + '"></a>');
`<a target="_blank" rel="noopener" href="${base_url}/logo/conversejs-filled.svg"><img src="${message}" class="chat-image img-thumbnail"></a>`);
message += "?param1=val1&param2=val2";
test_utils.sendMessage(view, message);
await u.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length === 2, 1000);
expect(view.model.sendMessage).toHaveBeenCalled();
msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
expect(msg.innerHTML.trim()).toEqual(
'<!-- src/templates/image.html -->\n'+
'<a href="'+base_url+'/logo/conversejs-filled.svg?param1=val1&amp;param2=val2" target="_blank" rel="noopener"><img'+
' class="chat-image img-thumbnail" src="'+message.replace(/&/g, '&amp;')+'"></a>')
'<a target="_blank" rel="noopener" href="'+base_url+'/logo/conversejs-filled.svg?param1=val1&amp;param2=val2"><img'+
' src="'+message.replace(/&/g, '&amp;')+'" class="chat-image img-thumbnail"></a>')
// Test now with two images in one message
message += ' hello world '+base_url+"/logo/conversejs-filled.svg";

View File

@ -276,7 +276,7 @@ converse.plugins.add('converse-message-view', {
if (text && text !== url) {
msg_content.innerHTML = await this.transformBodyText(text);
if (_converse.show_images_inline) {
await u.renderImageURLs(_converse, msg_content);
u.renderImageURLs(_converse, msg_content).then(() => this.triggerRendered());
}
}
}
@ -284,6 +284,10 @@ converse.plugins.add('converse-message-view', {
this.renderAvatar(msg);
}
this.replaceElement(msg);
this.triggerRendered();
},
triggerRendered () {
if (this.model.collection) {
// If the model gets destroyed in the meantime, it no
// longer has a collection.

View File

@ -54,14 +54,12 @@ function slideOutWrapup (el) {
function isImage (url) {
return new Promise((resolve, reject) => {
var img = new Image();
var timer = window.setTimeout(function () {
reject(new Error("Could not determine whether it's an image"));
img = null;
}, 3000);
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)), 3000);
img.onerror = img.onabort = function () {
clearTimeout(timer);
reject(new Error("Could not determine whether it's an image"));
reject(new Error(err_msg));
};
img.onload = function () {
clearTimeout(timer);
@ -182,15 +180,23 @@ u.applyDragResistance = function (value, default_value) {
};
function renderImage (img_url, link_url, el, callback) {
async function renderImage (img_url, link_url, el, callback) {
if (u.isImageURL(img_url)) {
return isImage(img_url)
.then(() => sizzle(`a[href="${link_url}"]`, el).forEach(a => (a.outerHTML = tpl_image({'url': img_url}))))
.then(callback)
.catch(callback);
} else {
return callback();
let img;
try {
img = await isImage(img_url);
} catch (e) {
log.error(e);
return callback();
}
sizzle(`a[href="${link_url}"]`, el).forEach(a => {
a.innerHTML = "";
u.addClass('chat-image', img);
u.addClass('img-thumbnail', img);
a.insertAdjacentElement('afterBegin', img);
});
}
callback();
}
@ -208,7 +214,7 @@ u.renderImageURLs = function (_converse, el) {
const list = el.textContent.match(URL_REGEX) || [];
return Promise.all(
list.map(url =>
new Promise((resolve) => {
new Promise(resolve => {
if (url.startsWith('https://imgur.com') && !u.isImageURL(url)) {
const imgur_url = url + '.png';
renderImage(imgur_url, url, el, resolve);