Fixes #2745. Wraps MUC details in converse-rich-text

Also fixed an issue where the `config` model on the MUC wasn't being
properly persisted and fetched.
This commit is contained in:
JC Brand 2022-02-14 19:19:47 +01:00
parent a2c7e83812
commit 85d75a5494
6 changed files with 34 additions and 14 deletions

View File

@ -137,7 +137,8 @@ const ChatRoomMixin = {
async restoreFromCache () {
if (this.isEntered() && (await this.isJoined())) {
// We've restored the room from cache and we're still joined.
await new Promise(resolve => this.features.fetch({ 'success': resolve, 'error': resolve }));
await new Promise(r => this.features.fetch({ 'success': r, 'error': r }));
await new Promise(r => this.config.fetch({ 'success': r, 'error': r }));
await this.fetchOccupants().catch(e => log.error(e));
await this.fetchMessages().catch(e => log.error(e));
return true;
@ -387,8 +388,8 @@ const ChatRoomMixin = {
this.features.browserStorage = _converse.createStore(id, 'session');
this.features.listenTo(_converse, 'beforeLogout', () => this.features.browserStorage.flush());
id = `converse.muc-config-{_converse.bare_jid}-${this.get('jid')}`;
this.config = new Model();
id = `converse.muc-config-${_converse.bare_jid}-${this.get('jid')}`;
this.config = new Model({ id });
this.config.browserStorage = _converse.createStore(id, 'session');
this.config.listenTo(_converse, 'beforeLogout', () => this.config.browserStorage.flush());
},
@ -1139,7 +1140,7 @@ const ChatRoomMixin = {
const fields = await api.disco.getFields(this.get('jid'));
const config = fields.reduce((config, f) => {
const name = f.get('var');
if (name && name.startsWith('muc#roominfo_')) {
if (name?.startsWith('muc#roominfo_')) {
config[name.replace('muc#roominfo_', '')] = f.get('value');
}
return config;

View File

@ -1,6 +1,8 @@
import BaseModal from "plugins/modal/base.js";
import tpl_muc_details from "./templates/muc-details.js";
import '../styles/muc-details.scss';
export default BaseModal.extend({
id: "muc-details-modal",

View File

@ -7,7 +7,7 @@ const subject = (o) => {
const i18n_topic = __('Topic');
const i18n_topic_author = __('Topic author');
return html`
<p class="room-info"><strong>${i18n_topic}</strong>: ${o.subject.text}</p>
<p class="room-info"><strong>${i18n_topic}</strong>: <converse-rich-text text=${o.subject.text} render_styling></converse-rich-text></p>
<p class="room-info"><strong>${i18n_topic_author}</strong>: ${o.subject && o.subject.author}</p>
`;
}
@ -20,7 +20,7 @@ export default (model) => {
const features = model.features.toJSON();
const num_occupants = model.occupants.filter(o => o.get('show') !== 'offline').length;
const i18n_address = __('Groupchat XMPP address');
const i18n_address = __('XMPP address');
const i18n_archiving = __('Message archiving');
const i18n_archiving_help = __('Messages are archived on the server');
const i18n_desc = __('Description');
@ -61,8 +61,8 @@ export default (model) => {
<span class="modal-alert"></span>
<div class="room-info">
<p class="room-info"><strong>${i18n_name}</strong>: ${o.name}</p>
<p class="room-info"><strong>${i18n_address}</strong>: ${o.jid}</p>
<p class="room-info"><strong>${i18n_desc}</strong>: ${config.description}</p>
<p class="room-info"><strong>${i18n_address}</strong>: <converse-rich-text text="xmpp:${o.jid}?join"></converse-rich-text></p>
<p class="room-info"><strong>${i18n_desc}</strong>: <converse-rich-text text="${config.description}" render_styling></converse-rich-text></p>
${ (o.subject) ? subject(o) : '' }
<p class="room-info"><strong>${i18n_online_users}</strong>: ${num_occupants}</p>
<p class="room-info"><strong>${i18n_features}</strong>:

View File

@ -0,0 +1,8 @@
#muc-details-modal {
.room-info {
strong {
color: var(--muc-color);
}
}
}

View File

@ -259,8 +259,12 @@ describe("A groupchat shown in the groupchats list", function () {
await u.waitUntil(() => u.isVisible(modal.el), 1000);
let els = modal.el.querySelectorAll('p.room-info');
expect(els[0].textContent).toBe("Name: A Dark Cave")
expect(els[1].textContent).toBe("Groupchat XMPP address: coven@chat.shakespeare.lit")
expect(els[2].textContent).toBe("Description: This is the description")
expect(els[1].querySelector('strong').textContent).toBe("XMPP address");
expect(els[1].querySelector('converse-rich-text').textContent.trim()).toBe("xmpp:coven@chat.shakespeare.lit?join");
expect(els[2].querySelector('strong').textContent).toBe("Description");
expect(els[2].querySelector('converse-rich-text').textContent).toBe("This is the description");
expect(els[3].textContent).toBe("Online users: 1")
const features_list = modal.el.querySelector('.features-list');
expect(features_list.textContent.replace(/(\n|\s{2,})/g, '')).toBe(
@ -289,9 +293,14 @@ describe("A groupchat shown in the groupchats list", function () {
view.model.set({'subject': {'author': 'someone', 'text': 'Hatching dark plots'}});
els = modal.el.querySelectorAll('p.room-info');
expect(els[0].textContent).toBe("Name: A Dark Cave")
expect(els[1].textContent).toBe("Groupchat XMPP address: coven@chat.shakespeare.lit")
expect(els[2].textContent).toBe("Description: This is the description")
expect(els[3].textContent).toBe("Topic: Hatching dark plots")
expect(els[1].querySelector('strong').textContent).toBe("XMPP address");
expect(els[1].querySelector('converse-rich-text').textContent.trim()).toBe("xmpp:coven@chat.shakespeare.lit?join");
expect(els[2].querySelector('strong').textContent).toBe("Description");
expect(els[2].querySelector('converse-rich-text').textContent).toBe("This is the description");
expect(els[3].querySelector('strong').textContent).toBe("Topic");
await u.waitUntil(() => els[3].querySelector('converse-rich-text').textContent === "Hatching dark plots");
expect(els[4].textContent).toBe("Topic author: someone")
expect(els[5].textContent).toBe("Online users: 2")
}));

View File

@ -123,7 +123,7 @@ export class RichText extends String {
*/
addHyperlinks (text, local_offset) {
const full_offset = local_offset + this.offset;
const urls_meta = this.media_urls || getMediaURLsMetadata(text).media_urls || [];
const urls_meta = this.media_urls || getMediaURLsMetadata(text, local_offset).media_urls || [];
const media_urls = getMediaURLs(urls_meta, text, full_offset);
media_urls.filter(o => !o.is_encrypted).forEach(url_obj => {