Commit 91c13075 authored by JC Brand's avatar JC Brand

chatview: Scroll down on image load

parent 282ffc62
/*global mock */ /*global mock, converse */
const { Promise, Strophe, $msg, dayjs, sizzle, _ } = converse.env; const { Promise, Strophe, $msg, dayjs, sizzle, _ } = converse.env;
const u = converse.env.utils; const u = converse.env.utils;
...@@ -999,7 +999,7 @@ describe("A Chat Message", function () { ...@@ -999,7 +999,7 @@ describe("A Chat Message", function () {
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop(); const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop();
await u.waitUntil(() => msg.innerHTML.replace(/<!---->/g, '').trim() == 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>`); `<a target="_blank" rel="noopener" href="https://conversejs.org/logo/non-existing.svg">https://conversejs.org/logo/non-existing.svg</a>`, 1000);
done(); done();
})); }));
......
...@@ -102,7 +102,7 @@ function addMapURLs (text) { ...@@ -102,7 +102,7 @@ function addMapURLs (text) {
} }
function addHyperlinks (text) { function addHyperlinks (text, onImgLoad) {
const objs = []; const objs = [];
try { try {
const parse_options = { 'start': /\b(?:([a-z][a-z0-9.+-]*:\/\/)|xmpp:|mailto:|www\.)/gi }; const parse_options = { 'start': /\b(?:([a-z][a-z0-9.+-]*:\/\/)|xmpp:|mailto:|www\.)/gi };
...@@ -120,7 +120,7 @@ function addHyperlinks (text) { ...@@ -120,7 +120,7 @@ function addHyperlinks (text) {
text.addTemplateResult( text.addTemplateResult(
url_obj.start, url_obj.start,
url_obj.end, url_obj.end,
show_images && u.isImageURL(url_text) ? u.convertToImageTag(url_text) : u.convertUrlToHyperlink(url_text), show_images && u.isImageURL(url_text) ? u.convertToImageTag(url_text, onImgLoad) : u.convertUrlToHyperlink(url_text),
); );
}); });
} }
...@@ -161,9 +161,21 @@ class MessageBodyRenderer { ...@@ -161,9 +161,21 @@ class MessageBodyRenderer {
constructor (component) { constructor (component) {
this.model = component.model; this.model = component.model;
this.component = component; this.component = component;
this.chatview = u.ancestor(this.component, 'converse-chat-message')?.chatview;
// We jot down whether we were scrolled down before rendering, because when an
// image loads, it triggers 'scroll' and the chat will be marked as scrolled,
// which is technically true, but not what we want because the user
// didn't initiate the scrolling.
this.scrolled = this.chatview.model.get('scrolled');
this.text = this.component.model.getMessageText(); this.text = this.component.model.getMessageText();
} }
scrollDownOnImageLoad () {
if (!this.scrolled) {
this.chatview.scrollDown();
}
}
async transform () { async transform () {
const text = new MessageText(this.text); const text = new MessageText(this.text);
/** /**
...@@ -179,7 +191,7 @@ class MessageBodyRenderer { ...@@ -179,7 +191,7 @@ class MessageBodyRenderer {
*/ */
await api.trigger('beforeMessageBodyTransformed', this.model, text, {'Synchronous': true}); await api.trigger('beforeMessageBodyTransformed', this.model, text, {'Synchronous': true});
addHyperlinks(text); addHyperlinks(text, () => this.scrollDownOnImageLoad());
addMapURLs(text); addMapURLs(text);
await addEmojis(text); await addEmojis(text);
addReferences(text, this.model); addReferences(text, this.model);
......
import { converse } from "@converse/headless/converse-core";
import { directive, html } from "lit-html"; import { directive, html } from "lit-html";
export const renderImage = directive(url => part => { export const renderImage = directive((url, onLoad) => part => {
function onError () { function onError () {
part.setValue(converse.env.utils.convertUrlToHyperlink(url)); part.setValue(converse.env.utils.convertUrlToHyperlink(url));
part.commit(); part.commit();
...@@ -11,6 +12,6 @@ export const renderImage = directive(url => part => { ...@@ -11,6 +12,6 @@ export const renderImage = directive(url => part => {
class="chat-image__link" class="chat-image__link"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
><img class="chat-image img-thumbnail" src="${url}" @error=${onError}/></a>` ><img class="chat-image img-thumbnail" src="${url}" @error=${onError} @load=${onLoad}/></a>`
); );
}); });
import { html } from "lit-html"; import { html } from "lit-html";
import { renderImage } from "./directives/image.js"; import { renderImage } from "./directives/image.js";
export default (o) => html`${renderImage(o.url)}`; export default (o) => html`${renderImage(o.url, o.onLoad)}`;
...@@ -290,15 +290,18 @@ u.escapeHTML = function (string) { ...@@ -290,15 +290,18 @@ u.escapeHTML = function (string) {
}; };
u.convertToImageTag = function (url) { u.convertToImageTag = function (url, onLoad) {
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());
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';
return tpl_image({'url': uri.removeSearch(/.*/).toString() + `.${format}`}); return tpl_image({
onLoad,
'url': uri.removeSearch(/.*/).toString() + `.${format}`
});
} else { } else {
return tpl_image({url}); return tpl_image({url, onLoad});
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment