muc-views: Update ListChatRoomsModal to make better use of lit-html

This commit is contained in:
JC Brand 2020-04-15 11:25:37 +02:00
parent 590bb8e3e0
commit f68f577b71
6 changed files with 96 additions and 82 deletions

View File

@ -14,25 +14,24 @@ import { render } from "lit-html";
import { __ } from '@converse/headless/i18n';
import converse from "@converse/headless/converse-core";
import log from "@converse/headless/log";
import st from "@converse/headless/utils/stanza";
import tpl_add_chatroom_modal from "templates/add_chatroom_modal.js";
import tpl_chatroom from "templates/chatroom.js";
import tpl_chatroom_bottom_panel from "templates/chatroom_bottom_panel.html";
import tpl_chatroom_destroyed from "templates/chatroom_destroyed.html";
import tpl_chatroom_details_modal from "templates/chatroom_details_modal.js";
import tpl_chatroom_disconnect from "templates/chatroom_disconnect.html";
import tpl_muc_config_form from "templates/muc_config_form.js";
import tpl_chatroom_head from "templates/chatroom_head.js";
import tpl_muc_invite_modal from "templates/muc_invite_modal.js";
import tpl_chatroom_nickname_form from "templates/chatroom_nickname_form.html";
import tpl_muc_password_form from "templates/muc_password_form.js";
import tpl_muc_sidebar from "templates/muc_sidebar.js";
import tpl_info from "templates/info.html";
import tpl_list_chatrooms_modal from "templates/list_chatrooms_modal.js";
import tpl_moderator_tools_modal from "templates/moderator_tools_modal.js";
import tpl_muc_config_form from "templates/muc_config_form.js";
import tpl_muc_invite_modal from "templates/muc_invite_modal.js";
import tpl_muc_password_form from "templates/muc_password_form.js";
import tpl_muc_sidebar from "templates/muc_sidebar.js";
import tpl_room_description from "templates/room_description.html";
import tpl_room_item from "templates/room_item.html";
import tpl_room_panel from "templates/room_panel.html";
import tpl_rooms_results from "templates/rooms_results.html";
import tpl_spinner from "templates/spinner.html";
import xss from "xss/dist/xss";
@ -408,15 +407,10 @@ converse.plugins.add('converse-muc-views', {
_converse.ListChatRoomsModal = BootstrapModal.extend({
id: "list-chatrooms-modal",
events: {
'submit form': 'showRooms',
'click a.room-info': 'toggleRoomInfo',
'change input[name=nick]': 'setNick',
'change input[name=server]': 'setDomainFromEvent',
'click .open-room': 'openRoom'
},
initialize () {
this.items = [];
this.loading_items = false;
BootstrapModal.prototype.initialize.apply(this, arguments);
if (_converse.muc_domain && !this.model.get('muc_domain')) {
this.model.save('muc_domain', _converse.muc_domain);
@ -426,9 +420,16 @@ converse.plugins.add('converse-muc-views', {
toHTML () {
const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
return tpl_list_chatrooms_modal(Object.assign(this.model.toJSON(), {
return tpl_list_chatrooms_modal(
Object.assign(this.model.toJSON(), {
'show_form': !_converse.locked_muc_domain,
'server_placeholder': muc_domain ? muc_domain : __('conference.example.org')
'server_placeholder': muc_domain ? muc_domain : __('conference.example.org'),
'items': this.items,
'loading_items': this.loading_items,
'openRoom': ev => this.openRoom(ev),
'setDomainFromEvent': ev => this.setDomainFromEvent(ev),
'submitForm': ev => this.showRooms(ev),
'toggleRoomInfo': ev => this.toggleRoomInfo(ev)
}));
},
@ -457,59 +458,35 @@ converse.plugins.add('converse-muc-views', {
},
onDomainChange () {
if (_converse.auto_list_rooms) {
this.updateRoomsList();
}
_converse.auto_list_rooms && this.updateRoomsList();
},
roomStanzaItemToHTMLElement (groupchat) {
const name = Strophe.unescapeNode(groupchat.getAttribute('name') || groupchat.getAttribute('jid'));
const div = document.createElement('div');
div.innerHTML = tpl_room_item({
'name': Strophe.xmlunescape(name),
'jid': groupchat.getAttribute('jid'),
'open_title': __('Click to open this groupchat'),
'info_title': __('Show more information on this groupchat')
});
return div.firstElementChild;
},
removeSpinner () {
sizzle('.spinner', this.el).forEach(u.removeElement);
},
informNoRoomsFound () {
const chatrooms_el = this.el.querySelector('.available-chatrooms');
chatrooms_el.innerHTML = tpl_rooms_results({'feedback_text': __('No groupchats found')});
const input_el = this.el.querySelector('input[name="server"]');
input_el.classList.remove('hidden')
this.removeSpinner();
},
onRoomsFound (iq) {
/* Handle the IQ stanza returned from the server, containing
/**
* Handle the IQ stanza returned from the server, containing
* all its public groupchats.
* @private
* @method _converse.ChatRoomView#onRoomsFound
* @param { HTMLElement } iq
*/
const available_chatrooms = this.el.querySelector('.available-chatrooms');
const rooms = sizzle('query item', iq);
onRoomsFound (iq) {
const rooms = iq ? sizzle('query item', iq) : [];
if (rooms.length) {
available_chatrooms.innerHTML = tpl_rooms_results({'feedback_text': __('Groupchats found:')});
const fragment = document.createDocumentFragment();
rooms.map(this.roomStanzaItemToHTMLElement)
.filter(r => r)
.forEach(child => fragment.appendChild(child));
available_chatrooms.appendChild(fragment);
this.removeSpinner();
this.model.set({'feedback_text': __('Groupchats found')}, {'silent': true});
this.items = rooms.map(st.getAttributes);
this.loading_items = false;
this.render();
} else {
this.informNoRoomsFound();
this.model.set('feedback_text', __('No groupchats found'));
}
return true;
},
updateRoomsList () {
/* Send an IQ stanza to the server asking for all groupchats
/**
* Send an IQ stanza to the server asking for all groupchats
* @private
* @method _converse.ChatRoomView#updateRoomsList
*/
updateRoomsList () {
const iq = $iq({
'to': this.model.get('muc_domain'),
'from': _converse.connection.jid,
@ -517,11 +494,14 @@ converse.plugins.add('converse-muc-views', {
}).c("query", {xmlns: Strophe.NS.DISCO_ITEMS});
api.sendIQ(iq)
.then(iq => this.onRoomsFound(iq))
.catch(() => this.informNoRoomsFound())
.catch(() => this.onRoomsFound())
},
showRooms (ev) {
ev.preventDefault();
this.loading_items = true;
this.render();
const data = new FormData(ev.target);
this.model.setDomain(data.get('server'));
this.updateRoomsList();

View File

@ -128,6 +128,20 @@ const stanza_utils = {
return !!sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop();
},
/**
* Returns an object containing all attribute names and values for a particular element.
* @private
* @method stanza_utils#getAttributes
* @param { XMLElement } stanza
* @returns { Object }
*/
getAttributes (stanza) {
return stanza.getAttributeNames().reduce((acc, name) => {
acc[name] = Strophe.xmlunescape(stanza.getAttribute(name))
return acc;
}, {});
},
/**
* Extract the XEP-0359 stanza IDs from the passed in stanza
* and return a map containing them.

View File

@ -1,23 +1,52 @@
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import { html } from "lit-html";
import { repeat } from 'lit-html/directives/repeat.js';
import { modal_close_button, modal_header_close_button } from "./buttons"
import spinner from "./spinner.js";
const i18n_info_title = __('Show more information on this groupchat');
const i18n_list_chatrooms = __('Query for Groupchats');
const i18n_server_address = __('Server address');
const i18n_open_title = __('Click to open this groupchat');
const i18n_query = __('Show groupchats');
const i18n_server_address = __('Server address');
const form = (o) => html`
<form class="converse-form list-chatrooms">
<form class="converse-form list-chatrooms"
@submit=${o.submitForm}>
<div class="form-group">
<label for="chatroom">${i18n_server_address}:</label>
<input type="text" value="${o.muc_domain}" required="required" name="server" class="form-control" placeholder="${o.server_placeholder}"/>
<input type="text"
@change=${o.setDomainFromEvent}
value="${o.muc_domain}"
required="required"
name="server"
class="form-control"
placeholder="${o.server_placeholder}"/>
</div>
<input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/>
</form>
`;
const tpl_item = (o, item) => html`
<li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100"
@click=${o.openRoom}
data-room-jid="${item.jid}"
data-room-name="${item.name}"
title="${i18n_open_title}"
href="#">${item.name || item.jid}</a>
<a class="right room-info icon-room-info"
@click=${o.toggleRoomInfo}
data-room-jid="${item.jid}"
title="${i18n_info_title}"
href="#"></a>
</div>
</li>
`;
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
@ -28,7 +57,11 @@ export default (o) => html`
<div class="modal-body d-flex flex-column">
<span class="modal-alert"></span>
${o.show_form ? form(o) : '' }
<ul class="available-chatrooms list-group"></ul>
<ul class="available-chatrooms list-group">
${ o.loading_items ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
${ o.items.length ? html`<li class="list-group-item active">${ o.feedback_text }:</li>` : '' }
${repeat(o.items, item => item.jid, item => tpl_item(o, item))}
</ul>
</div>
<div class="modal-footer">${modal_close_button}</div>
</div>

View File

@ -1,12 +0,0 @@
<li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100"
data-room-jid="{{{o.jid}}}"
data-room-name="{{{o.name}}}"
title="{{{o.open_title}}}"
href="#">{{{o.name}}}</a>
<a class="right room-info icon-room-info"
data-room-jid="{{{o.jid}}}"
title="{{{o.info_title}}}" href="#"></a>
</div>
</li>

View File

@ -1 +0,0 @@
<li class="list-group-item active">{{{ o.feedback_text }}}</li>