Use API to get chat/room models in components

This commit is contained in:
JC Brand 2021-06-22 14:07:45 +02:00
parent afd737f965
commit 6dea5959cc
6 changed files with 56 additions and 31 deletions

View File

@ -15,17 +15,26 @@ export default class ChatBottomPanel extends ElementView {
'click .toggle-clear': 'clearMessages'
};
constructor () {
super();
this.debouncedRender = debounce(this.render, 100);
}
async connectedCallback () {
super.connectedCallback();
this.debouncedRender = debounce(this.render, 100);
this.model = _converse.chatboxes.get(this.getAttribute('jid'));
await this.initialize();
this.render(); // don't call in initialize, since the MUCBottomPanel subclasses it
// and we want to render after it has finished as wel.
}
async initialize () {
this.model = await api.chatboxes.get(this.getAttribute('jid'));
await this.model.initialized;
this.listenTo(this.model, 'change:num_unread', this.debouncedRender)
this.listenTo(this.model, 'emoji-picker-autocomplete', this.autocompleteInPicker);
this.addEventListener('focusin', ev => this.emitFocused(ev));
this.addEventListener('focusout', ev => this.emitBlurred(ev));
this.render();
}
render () {

View File

@ -14,8 +14,7 @@ describe("A Chat Message", function () {
await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid);
await _converse.handleMessageStanza(mock.createChatMessage(_converse, contact_jid, 'This message will be read'));
const msg_el = await u.waitUntil(() => view.querySelector('converse-chat-message'));
expect(msg_el.querySelector('.chat-msg__text').textContent).toBe('This message will be read');
await u.waitUntil(() => view.querySelector('converse-chat-message .chat-msg__text')?.textContent === 'This message will be read');
expect(view.model.get('num_unread')).toBe(0);
_converse.windowState = 'hidden';
@ -26,6 +25,7 @@ describe("A Chat Message", function () {
expect(view.model.get('first_unread_id')).toBe(view.model.messages.last().get('id'));
await u.waitUntil(() => view.querySelectorAll('converse-chat-message').length === 2);
await u.waitUntil(() => view.querySelector('converse-chat-message:last-child .chat-msg__text')?.textContent === 'This message will be new');
const last_msg_el = view.querySelector('converse-chat-message:last-child');
expect(last_msg_el.firstElementChild?.textContent).toBe('New messages');
done();

View File

@ -1,6 +1,5 @@
import 'shared/autocomplete/index.js';
import BottomPanel from 'plugins/chatview/bottom-panel.js';
import debounce from 'lodash-es/debounce';
import tpl_muc_bottom_panel from './templates/muc-bottom-panel.js';
import { _converse, api, converse } from "@converse/headless/core";
import { render } from 'lit';
@ -15,17 +14,14 @@ export default class MUCBottomPanel extends BottomPanel {
'click .send-button': 'sendButtonClicked',
}
async connectedCallback () {
// this.model gets set in the super method and we also wait there for this.model.initialized
await super.connectedCallback();
this.debouncedRender = debounce(this.render, 100);
async initialize () {
await super.initialize();
this.listenTo(this.model, 'change:hidden_occupants', this.debouncedRender);
this.listenTo(this.model, 'change:num_unread_general', this.debouncedRender)
this.listenTo(this.model.features, 'change:moderated', this.debouncedRender);
this.listenTo(this.model.occupants, 'add', this.renderIfOwnOccupant)
this.listenTo(this.model.occupants, 'change:role', this.renderIfOwnOccupant);
this.listenTo(this.model.session, 'change:connection_status', this.debouncedRender);
this.render();
}
render () {

View File

@ -12,7 +12,7 @@ describe("Emojis", function () {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.querySelector('converse-emoji-dropdown'));
await u.waitUntil(() => view.querySelector('converse-emoji-picker'));
const textarea = view.querySelector('textarea.chat-textarea');
textarea.value = ':gri';
@ -80,7 +80,7 @@ describe("Emojis", function () {
await mock.waitForRoster(_converse, 'current', 0);
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.querySelector('converse-emoji-dropdown'));
await u.waitUntil(() => view.querySelector('converse-emoji-picker'));
const textarea = view.querySelector('textarea.chat-textarea');
textarea.value = ':';
// Press tab
@ -130,7 +130,7 @@ describe("Emojis", function () {
await mock.waitForRoster(_converse, 'current', 0);
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.querySelector('converse-emoji-dropdown'));
await u.waitUntil(() => view.querySelector('converse-emoji-picker'));
const textarea = view.querySelector('textarea.chat-textarea');
textarea.value = ':gri';

View File

@ -1,6 +1,6 @@
import './message-history';
import { CustomElement } from 'shared/components/element.js';
import { _converse, api } from '@converse/headless/core';
import { api } from '@converse/headless/core';
import { html } from 'lit';
import { markScrolled } from './utils.js';
@ -25,8 +25,8 @@ export default class ChatContent extends CustomElement {
this.removeEventListener('scroll', markScrolled);
}
initialize () {
this.model = _converse.chatboxes.get(this.jid);
async initialize () {
await this.setModels();
this.listenTo(this.model, 'change:hidden_occupants', this.requestUpdate);
this.listenTo(this.model.messages, 'add', this.requestUpdate);
this.listenTo(this.model.messages, 'change', this.requestUpdate);
@ -43,7 +43,16 @@ export default class ChatContent extends CustomElement {
this.addEventListener('scroll', markScrolled);
}
async setModels () {
this.model = await api.chatboxes.get(this.jid);
await this.model.initialized;
this.requestUpdate();
}
render () {
if (!this.model) {
return '';
}
// This element has "flex-direction: reverse", so elements here are
// shown in reverse order.
return html`

View File

@ -28,23 +28,13 @@ export default class Message extends CustomElement {
}
}
render () {
if (this.show_spinner) {
return tpl_spinner();
} else if (this.model.get('file') && !this.model.get('oob_url')) {
return this.renderFileProgress();
} else if (['error', 'info'].includes(this.model.get('type'))) {
return this.renderInfoMessage();
} else {
return this.renderChatMessage();
}
}
connectedCallback () {
super.connectedCallback();
this.chatbox = _converse.chatboxes.get(this.jid);
this.model = this.chatbox.messages.get(this.mid);
this.initialize();
}
async initialize () {
await this.setModels();
this.listenTo(this.chatbox, 'change:first_unread_id', this.requestUpdate);
this.listenTo(this.model, 'change', this.requestUpdate);
this.model.vcard && this.listenTo(this.model.vcard, 'change', this.requestUpdate);
@ -60,6 +50,27 @@ export default class Message extends CustomElement {
}
}
async setModels () {
this.chatbox = await api.chatboxes.get(this.jid);
await this.chatbox.initialized;
this.model = this.chatbox.messages.get(this.mid);
this.requestUpdate();
}
render () {
if (!this.model) {
return '';
} else if (this.show_spinner) {
return tpl_spinner();
} else if (this.model.get('file') && !this.model.get('oob_url')) {
return this.renderFileProgress();
} else if (['error', 'info'].includes(this.model.get('type'))) {
return this.renderInfoMessage();
} else {
return this.renderChatMessage();
}
}
getProps () {
return Object.assign(
this.model.toJSON(),