Turn the chats into Lit components

Previously they were of type ElementView from @converse/skeletor

The ElementView component is merely a helper to allow us to eventually
migrate everything to Lit
This commit is contained in:
JC Brand 2021-06-04 15:21:39 +02:00
parent 06c4ded063
commit e3612e8c62
5 changed files with 41 additions and 66 deletions

View File

@ -1,30 +1,27 @@
import 'plugins/chatview/heading.js'; import 'plugins/chatview/heading.js';
import 'plugins/chatview/bottom-panel.js'; import 'plugins/chatview/bottom-panel.js';
import { render } from 'lit';
import BaseChatView from 'shared/chat/baseview.js'; import BaseChatView from 'shared/chat/baseview.js';
import tpl_chat from './templates/chat.js'; import tpl_chat from './templates/chat.js';
import { __ } from 'i18n'; import { __ } from 'i18n';
import { _converse, api } from '@converse/headless/core'; import { _converse, api } from '@converse/headless/core';
/** /**
* The View of an open/ongoing chat conversation. * The view of an open/ongoing chat conversation.
* @class * @class
* @namespace _converse.ChatBoxView * @namespace _converse.ChatBoxView
* @memberOf _converse * @memberOf _converse
*/ */
export default class ChatView extends BaseChatView { export default class ChatView extends BaseChatView {
length = 200 length = 200
className = 'chatbox hidden'
async initialize () { async connectedCallback () {
const jid = this.getAttribute('jid'); super.connectedCallback();
_converse.chatboxviews.add(jid, this); _converse.chatboxviews.add(this.jid, this);
this.model = _converse.chatboxes.get(jid); this.model = _converse.chatboxes.get(this.jid);
this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged); this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged);
this.listenTo(this.model, 'change:hidden', () => !this.model.get('hidden') && this.afterShown()); this.listenTo(this.model, 'change:hidden', () => !this.model.get('hidden') && this.afterShown());
this.listenTo(this.model, 'change:show_help_messages', this.render); this.listenTo(this.model, 'change:show_help_messages', this.requestUpdate);
this.listenTo(this.model, 'change:status', this.onStatusMessageChanged); this.listenTo(this.model, 'change:status', this.onStatusMessageChanged);
this.render();
await this.model.messages.fetched; await this.model.messages.fetched;
!this.model.get('hidden') && this.afterShown() !this.model.get('hidden') && this.afterShown()
@ -37,7 +34,7 @@ export default class ChatView extends BaseChatView {
api.trigger('chatBoxViewInitialized', this); api.trigger('chatBoxViewInitialized', this);
} }
toHTML () { render () {
return tpl_chat(Object.assign({ return tpl_chat(Object.assign({
'model': this.model, 'model': this.model,
'help_messages': this.getHelpMessages(), 'help_messages': this.getHelpMessages(),
@ -54,10 +51,9 @@ export default class ChatView extends BaseChatView {
]; ];
} }
showControlBox () { showControlBox () { // eslint-disable-line class-methods-use-this
// Used in mobile view, to navigate back to the controlbox // Used in mobile view, to navigate back to the controlbox
_converse.chatboxviews.get('controlbox')?.show(); _converse.chatboxviews.get('controlbox')?.show();
this.hide();
} }
/** /**

View File

@ -1,28 +1,23 @@
import BaseChatView from 'shared/chat/baseview.js'; import BaseChatView from 'shared/chat/baseview.js';
import tpl_headlines from './templates/headlines.js'; import tpl_headlines from './templates/headlines.js';
import { _converse, api } from '@converse/headless/core'; import { _converse, api } from '@converse/headless/core';
import { render } from 'lit';
class HeadlinesView extends BaseChatView { class HeadlinesView extends BaseChatView {
async initialize () { async connectedCallback () {
const jid = this.getAttribute('jid'); super.connectedCallback();
_converse.chatboxviews.add(jid, this); _converse.chatboxviews.add(this.jid, this);
this.model = _converse.chatboxes.get(jid); this.model = _converse.chatboxes.get(this.jid);
this.model.disable_mam = true; // Don't do MAM queries for this box this.model.disable_mam = true; // Don't do MAM queries for this box
this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged);
this.listenTo(this.model, 'change:hidden', () => this.afterShown()); this.listenTo(this.model, 'change:hidden', () => this.afterShown());
this.listenTo(this.model, 'destroy', this.remove); this.listenTo(this.model, 'destroy', this.remove);
this.listenTo(this.model, 'show', this.show); this.listenTo(this.model, 'show', this.show);
this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged); this.listenTo(this.model.messages, 'add', this.requestUpdate);
this.listenTo(this.model.messages, 'remove', this.requestUpdate);
this.render(); this.listenTo(this.model.messages, 'reset', this.requestUpdate);
// Need to be registered after render has been called.
this.listenTo(this.model.messages, 'add', this.onMessageAdded);
this.listenTo(this.model.messages, 'remove', this.renderChatHistory);
this.listenTo(this.model.messages, 'reset', this.renderChatHistory);
await this.model.messages.fetched; await this.model.messages.fetched;
this.model.maybeShow(); this.model.maybeShow();
@ -37,15 +32,12 @@ class HeadlinesView extends BaseChatView {
} }
render () { render () {
this.setAttribute('id', this.model.get('box_id')); return tpl_headlines(
const result = tpl_headlines(
Object.assign(this.model.toJSON(), { Object.assign(this.model.toJSON(), {
show_send_button: false, show_send_button: false,
show_toolbar: false, show_toolbar: false,
}) })
); );
render(result, this);
return this;
} }
async close (ev) { async close (ev) {
@ -58,7 +50,6 @@ class HeadlinesView extends BaseChatView {
return this; return this;
} }
getNotifications () { // eslint-disable-line class-methods-use-this getNotifications () { // eslint-disable-line class-methods-use-this
// Override method in ChatBox. We don't show notifications for // Override method in ChatBox. We don't show notifications for
// headlines boxes. // headlines boxes.

View File

@ -3,31 +3,25 @@ import log from '@converse/headless/log';
import tpl_muc from './templates/muc.js'; import tpl_muc from './templates/muc.js';
import { __ } from 'i18n'; import { __ } from 'i18n';
import { _converse, api, converse } from '@converse/headless/core'; import { _converse, api, converse } from '@converse/headless/core';
import { render } from "lit";
export default class MUCView extends BaseChatView { export default class MUCView extends BaseChatView {
length = 300 length = 300
is_chatroom = true is_chatroom = true
async initialize () { async connectedCallback () {
const jid = this.getAttribute('jid'); super.connectedCallback();
this.model = await api.rooms.get(jid); this.model = await api.rooms.get(this.jid);
_converse.chatboxviews.add(jid, this); _converse.chatboxviews.add(this.jid, this);
this.setAttribute('id', this.model.get('box_id')); this.setAttribute('id', this.model.get('box_id'));
this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged); this.listenTo(_converse, 'windowStateChanged', this.onWindowStateChanged);
this.listenTo(this.model, 'change:composing_spoiler', this.renderMessageForm); this.listenTo(this.model, 'change:composing_spoiler', this.requestUpdateMessageForm);
this.listenTo(this.model, 'change:hidden', () => this.afterShown()); this.listenTo(this.model, 'change:hidden', () => this.afterShown());
this.listenTo(this.model, 'change:minimized', () => this.afterShown()); this.listenTo(this.model, 'change:minimized', () => this.afterShown());
this.listenTo(this.model, 'show', this.show); this.listenTo(this.model, 'show', this.show);
this.listenTo(this.model.session, 'change:connection_status', this.updateAfterTransition); this.listenTo(this.model.session, 'change:connection_status', this.updateAfterTransition);
this.listenTo(this.model.session, 'change:view', this.render); this.listenTo(this.model.session, 'change:view', this.requestUpdate);
await this.render();
// Need to be registered after render has been called.
this.listenTo(this.model.occupants, 'change:show', this.showJoinOrLeaveNotification);
this.updateAfterTransition(); this.updateAfterTransition();
this.model.maybeShow(); this.model.maybeShow();
@ -42,8 +36,7 @@ export default class MUCView extends BaseChatView {
} }
render () { render () {
render(tpl_muc({ 'model': this.model }), this); return this.model ? tpl_muc({ 'model': this.model }) : '';
!this.model.get('hidden') && this.show();
} }
/** /**
@ -115,7 +108,7 @@ export default class MUCView extends BaseChatView {
'reason': undefined, 'reason': undefined,
}); });
} }
this.render(); this.requestUpdate();
} }
} }

View File

@ -1271,6 +1271,10 @@ describe("Groupchats", function () {
view.querySelector('.configure-chatroom-button').click(); view.querySelector('.configure-chatroom-button').click();
const sent_IQs = _converse.connection.IQ_stanzas;
const sel = 'iq query[xmlns="http://jabber.org/protocol/muc#owner"]';
const iq = await u.waitUntil(() => sent_IQs.filter(iq => sizzle(sel, iq).length).pop());
/* Check that an IQ is sent out, asking for the /* Check that an IQ is sent out, asking for the
* configuration form. * configuration form.
* See: // https://xmpp.org/extensions/xep-0045.html#example-163 * See: // https://xmpp.org/extensions/xep-0045.html#example-163
@ -1282,8 +1286,8 @@ describe("Groupchats", function () {
* <query xmlns='http://jabber.org/protocol/muc#owner'/> * <query xmlns='http://jabber.org/protocol/muc#owner'/>
* </iq> * </iq>
*/ */
expect(Strophe.serialize(sent_IQ)).toBe( expect(Strophe.serialize(iq)).toBe(
`<iq id="`+IQ_id+`" to="coven@chat.shakespeare.lit" type="get" xmlns="jabber:client">`+ `<iq id="${iq.getAttribute('id')}" to="coven@chat.shakespeare.lit" type="get" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/muc#owner"/>`+ `<query xmlns="http://jabber.org/protocol/muc#owner"/>`+
`</iq>`); `</iq>`);
@ -1291,7 +1295,7 @@ describe("Groupchats", function () {
* See: // https://xmpp.org/extensions/xep-0045.html#example-165 * See: // https://xmpp.org/extensions/xep-0045.html#example-165
*/ */
const config_stanza = $iq({from: 'coven@chat.shakespeare.lit', const config_stanza = $iq({from: 'coven@chat.shakespeare.lit',
'id': IQ_id, 'id': iq.getAttribute('id'),
'to': 'romeo@montague.lit/desktop', 'to': 'romeo@montague.lit/desktop',
'type': 'result'}) 'type': 'result'})
.c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'}) .c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'})

View File

@ -1,16 +1,20 @@
import log from '@converse/headless/log'; import { CustomElement } from 'shared/components/element.js';
import { ElementView } from '@converse/skeletor/src/element.js';
import { _converse, api, converse } from '@converse/headless/core'; import { _converse, api, converse } from '@converse/headless/core';
import { onScrolledDown } from './utils.js'; import { onScrolledDown } from './utils.js';
const u = converse.env.utils; const u = converse.env.utils;
export default class BaseChatView extends ElementView { export default class BaseChatView extends CustomElement {
static get properties () {
return {
jid: { type: String }
}
}
disconnectedCallback () { disconnectedCallback () {
super.disconnectedCallback(); super.disconnectedCallback();
const jid = this.getAttribute('jid'); _converse.chatboxviews.remove(this.jid, this);
_converse.chatboxviews.remove(jid, this);
} }
maybeFocus () { maybeFocus () {
@ -24,19 +28,6 @@ export default class BaseChatView extends ElementView {
} }
return this; return this;
} }
show () {
if (this.model.get('hidden')) {
log.debug(`Not showing chat ${this.model.get('jid')} because it's set as hidden`);
return;
}
if (u.isVisible(this)) {
this.maybeFocus();
return;
}
this.afterShown();
}
emitBlurred (ev) { emitBlurred (ev) {
if (this.contains(document.activeElement) || this.contains(ev.relatedTarget)) { if (this.contains(document.activeElement) || this.contains(ev.relatedTarget)) {
// Something else in this chatbox is still focused // Something else in this chatbox is still focused