MUC: Don't show topic change notification for old changes.
Also, show topic by creating a message object, instead of directly inserting HTML into the DOM. This is a necessary precursor to being able to render chat messages via lit-html/lit-element.
This commit is contained in:
parent
3e27a5ec81
commit
5fd316816d
65
spec/muc.js
65
spec/muc.js
@ -501,7 +501,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("the topic", function () {
|
describe("topic", function () {
|
||||||
|
|
||||||
it("is shown the header",
|
it("is shown the header",
|
||||||
mock.initConverse(
|
mock.initConverse(
|
||||||
@ -511,7 +511,7 @@
|
|||||||
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
|
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
|
||||||
const text = 'Jabber/XMPP Development | RFCs and Extensions: https://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
const text = 'Jabber/XMPP Development | RFCs and Extensions: https://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
||||||
let stanza = u.toStanza(`
|
let stanza = u.toStanza(`
|
||||||
<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
<subject>${text}</subject>
|
<subject>${text}</subject>
|
||||||
<delay xmlns="urn:xmpp:delay" stamp="2014-02-04T09:35:39Z" from="jdev@conference.jabber.org"/>
|
<delay xmlns="urn:xmpp:delay" stamp="2014-02-04T09:35:39Z" from="jdev@conference.jabber.org"/>
|
||||||
<x xmlns="jabber:x:delay" stamp="20140204T09:35:39" from="jdev@conference.jabber.org"/>
|
<x xmlns="jabber:x:delay" stamp="20140204T09:35:39" from="jdev@conference.jabber.org"/>
|
||||||
@ -520,12 +520,11 @@
|
|||||||
const view = _converse.chatboxviews.get('jdev@conference.jabber.org');
|
const view = _converse.chatboxviews.get('jdev@conference.jabber.org');
|
||||||
await new Promise(resolve => view.model.once('change:subject', resolve));
|
await new Promise(resolve => view.model.once('change:subject', resolve));
|
||||||
|
|
||||||
expect(sizzle('.chat-event:last', view.el).pop().textContent.trim()).toBe('Topic set by ralphm');
|
|
||||||
const head_desc = await u.waitUntil(() => view.el.querySelector('.chat-head__desc'));
|
const head_desc = await u.waitUntil(() => view.el.querySelector('.chat-head__desc'));
|
||||||
expect(head_desc?.textContent.trim()).toBe(text);
|
expect(head_desc?.textContent.trim()).toBe(text);
|
||||||
|
|
||||||
stanza = u.toStanza(
|
stanza = u.toStanza(
|
||||||
`<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
`<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
<subject>This is a message subject</subject>
|
<subject>This is a message subject</subject>
|
||||||
<body>This is a message</body>
|
<body>This is a message</body>
|
||||||
</message>`);
|
</message>`);
|
||||||
@ -536,16 +535,6 @@
|
|||||||
expect(sizzle('.chat-msg__text').length).toBe(1);
|
expect(sizzle('.chat-msg__text').length).toBe(1);
|
||||||
expect(sizzle('.chat-msg__text').pop().textContent.trim()).toBe('This is a message');
|
expect(sizzle('.chat-msg__text').pop().textContent.trim()).toBe('This is a message');
|
||||||
expect(view.el.querySelector('.chat-head__desc').textContent.trim()).toBe(text);
|
expect(view.el.querySelector('.chat-head__desc').textContent.trim()).toBe(text);
|
||||||
|
|
||||||
// Removes current topic
|
|
||||||
stanza = u.toStanza(
|
|
||||||
`<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
|
||||||
<subject/>
|
|
||||||
</message>`);
|
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
||||||
await new Promise(resolve => view.model.once('change:subject', resolve));
|
|
||||||
await u.waitUntil(() => view.el.querySelector('.chat-head__desc') === null);
|
|
||||||
expect(view.el.querySelector('.chat-info:last-child').textContent.trim()).toBe("Topic cleared by ralphm");
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -557,7 +546,7 @@
|
|||||||
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
|
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
|
||||||
const text = 'Jabber/XMPP Development | RFCs and Extensions: https://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
const text = 'Jabber/XMPP Development | RFCs and Extensions: https://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
||||||
let stanza = u.toStanza(`
|
let stanza = u.toStanza(`
|
||||||
<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
<subject>${text}</subject>
|
<subject>${text}</subject>
|
||||||
<delay xmlns="urn:xmpp:delay" stamp="2014-02-04T09:35:39Z" from="jdev@conference.jabber.org"/>
|
<delay xmlns="urn:xmpp:delay" stamp="2014-02-04T09:35:39Z" from="jdev@conference.jabber.org"/>
|
||||||
<x xmlns="jabber:x:delay" stamp="20140204T09:35:39" from="jdev@conference.jabber.org"/>
|
<x xmlns="jabber:x:delay" stamp="20140204T09:35:39" from="jdev@conference.jabber.org"/>
|
||||||
@ -566,12 +555,11 @@
|
|||||||
const view = _converse.chatboxviews.get('jdev@conference.jabber.org');
|
const view = _converse.chatboxviews.get('jdev@conference.jabber.org');
|
||||||
await new Promise(resolve => view.model.once('change:subject', resolve));
|
await new Promise(resolve => view.model.once('change:subject', resolve));
|
||||||
|
|
||||||
expect(sizzle('.chat-event:last', view.el).pop().textContent.trim()).toBe('Topic set by ralphm');
|
|
||||||
const head_desc = await u.waitUntil(() => view.el.querySelector('.chat-head__desc'));
|
const head_desc = await u.waitUntil(() => view.el.querySelector('.chat-head__desc'));
|
||||||
expect(head_desc?.textContent.trim()).toBe(text);
|
expect(head_desc?.textContent.trim()).toBe(text);
|
||||||
|
|
||||||
stanza = u.toStanza(
|
stanza = u.toStanza(
|
||||||
`<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
`<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
<subject>This is a message subject</subject>
|
<subject>This is a message subject</subject>
|
||||||
<body>This is a message</body>
|
<body>This is a message</body>
|
||||||
</message>`);
|
</message>`);
|
||||||
@ -592,6 +580,49 @@
|
|||||||
expect(view.el.querySelector('.hide-topic').textContent).toBe('Show topic');
|
expect(view.el.querySelector('.hide-topic').textContent).toBe('Show topic');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("causes an info message to be shown when received in real-time",
|
||||||
|
mock.initConverse(
|
||||||
|
['rosterGroupsFetched'], {},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
spyOn(_converse.ChatRoom.prototype, 'handleSubjectChange').and.callThrough();
|
||||||
|
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'romeo');
|
||||||
|
const view = _converse.chatboxviews.get('jdev@conference.jabber.org');
|
||||||
|
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(u.toStanza(`
|
||||||
|
<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
|
<subject>This is an older topic</subject>
|
||||||
|
<delay xmlns="urn:xmpp:delay" stamp="2014-02-04T09:35:39Z" from="jdev@conference.jabber.org"/>
|
||||||
|
<x xmlns="jabber:x:delay" stamp="20140204T09:35:39" from="jdev@conference.jabber.org"/>
|
||||||
|
</message>`)));
|
||||||
|
await u.waitUntil(() => view.model.handleSubjectChange.calls.count());
|
||||||
|
expect(sizzle('.chat-info__message', view.el).length).toBe(0);
|
||||||
|
|
||||||
|
const desc = await u.waitUntil(() => view.el.querySelector('.chat-head__desc'));
|
||||||
|
expect(desc.textContent.trim()).toBe('This is an older topic');
|
||||||
|
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(u.toStanza(`
|
||||||
|
<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
|
<subject>This is a new topic</subject>
|
||||||
|
</message>`)));
|
||||||
|
await u.waitUntil(() => view.model.handleSubjectChange.calls.count() === 2);
|
||||||
|
|
||||||
|
const el = sizzle('.chat-info__message', view.el).pop();
|
||||||
|
expect(el.textContent.trim()).toBe('Topic set by ralphm');
|
||||||
|
await u.waitUntil(() => desc.textContent.trim() === 'This is a new topic');
|
||||||
|
|
||||||
|
// Removes current topic
|
||||||
|
const stanza = u.toStanza(
|
||||||
|
`<message xmlns="jabber:client" to="${_converse.jid}" type="groupchat" from="jdev@conference.jabber.org/ralphm">
|
||||||
|
<subject/>
|
||||||
|
</message>`);
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
await u.waitUntil(() => view.model.handleSubjectChange.calls.count() === 3);
|
||||||
|
await u.waitUntil(() => view.el.querySelector('.chat-head__desc') === null);
|
||||||
|
expect(view.el.querySelector('.chat-info:last-child').textContent.trim()).toBe("Topic cleared by ralphm");
|
||||||
|
done();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,8 +235,8 @@
|
|||||||
'text': subject,
|
'text': subject,
|
||||||
'author': 'ralphm'
|
'author': 'ralphm'
|
||||||
}});
|
}});
|
||||||
expect(sizzle('.chat-event:last').pop().textContent.trim()).toBe('Topic set by ralphm');
|
const text = await u.waitUntil(() => view.el.querySelector('.chat-head__desc')?.textContent.trim());
|
||||||
await u.waitUntil(() => view.el.querySelector('.chat-head__desc')?.textContent.trim() === subject);
|
expect(text).toBe(subject);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -708,7 +708,6 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
|
|
||||||
this.listenTo(this.model, 'change', debounce(() => this.renderHeading(), 250));
|
this.listenTo(this.model, 'change', debounce(() => this.renderHeading(), 250));
|
||||||
this.listenTo(this.model, 'change:hidden_occupants', this.updateOccupantsToggle);
|
this.listenTo(this.model, 'change:hidden_occupants', this.updateOccupantsToggle);
|
||||||
this.listenTo(this.model, 'change:subject', this.setChatRoomSubject);
|
|
||||||
this.listenTo(this.model, 'configurationNeeded', this.getAndRenderConfigurationForm);
|
this.listenTo(this.model, 'configurationNeeded', this.getAndRenderConfigurationForm);
|
||||||
this.listenTo(this.model, 'destroy', this.hide);
|
this.listenTo(this.model, 'destroy', this.hide);
|
||||||
this.listenTo(this.model, 'show', this.show);
|
this.listenTo(this.model, 'show', this.show);
|
||||||
@ -2004,26 +2003,6 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
this.renderAfterTransition();
|
this.renderAfterTransition();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
|
||||||
|
|
||||||
setChatRoomSubject () {
|
|
||||||
const subject = this.model.get('subject');
|
|
||||||
if (!subject.text && !subject.author) {
|
|
||||||
return; // Probably a new MUC
|
|
||||||
}
|
|
||||||
const author = subject.author;
|
|
||||||
// For translators: the %1$s part will get
|
|
||||||
// replaced by the user's name.
|
|
||||||
// Example: Topic set by JC Brand
|
|
||||||
const message = subject.text ? __('Topic set by %1$s', author) : __('Topic cleared by %1$s', author);
|
|
||||||
this.msgs_container.insertAdjacentHTML(
|
|
||||||
'beforeend',
|
|
||||||
tpl_info({
|
|
||||||
'isodate': (new Date()).toISOString(),
|
|
||||||
'extra_classes': 'chat-event',
|
|
||||||
'message': message
|
|
||||||
}));
|
|
||||||
this.scrollDown();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1682,22 +1682,34 @@ converse.plugins.add('converse-muc', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a subject change and return `true` if so.
|
* Handle a possible subject change and return `true` if so.
|
||||||
* @private
|
* @private
|
||||||
* @method _converse.ChatRoom#subjectChangeHandled
|
* @method _converse.ChatRoom#handleSubjectChange
|
||||||
* @param { object } attrs - The message attributes
|
* @param { object } attrs - Attributes representing a received
|
||||||
|
* message, as returned by {@link stanza_utils.getMessageAttributesFromStanza}
|
||||||
*/
|
*/
|
||||||
subjectChangeHandled (attrs) {
|
handleSubjectChange (attrs) {
|
||||||
if (isString(attrs.subject) && !attrs.thread && !attrs.message) {
|
if (isString(attrs.subject) && !attrs.thread && !attrs.message) {
|
||||||
// https://xmpp.org/extensions/xep-0045.html#subject-mod
|
// https://xmpp.org/extensions/xep-0045.html#subject-mod
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// The subject is changed by sending a message of type "groupchat" to the <room@service>,
|
// The subject is changed by sending a message of type "groupchat" to the <room@service>,
|
||||||
// where the <message/> MUST contain a <subject/> element that specifies the new subject but
|
// where the <message/> MUST contain a <subject/> element that specifies the new subject but
|
||||||
// MUST NOT contain a <body/> element (or a <thread/> element).
|
// MUST NOT contain a <body/> element (or a <thread/> element).
|
||||||
|
const subject = attrs.subject;
|
||||||
|
const author = attrs.nick;
|
||||||
u.safeSave(this, {
|
u.safeSave(this, {
|
||||||
'subject': {'author': attrs.nick, 'text': attrs.subject || ''},
|
'subject': {author, 'text': attrs.subject || ''},
|
||||||
'subject_hidden': attrs.subject ? false : this.get('subject_hidden')
|
'subject_hidden': subject ? false : this.get('subject_hidden')
|
||||||
});
|
});
|
||||||
|
if (!attrs.is_delayed) {
|
||||||
|
const message = subject ? __('Topic set by %1$s', author) : __('Topic cleared by %1$s', author);
|
||||||
|
const data = {
|
||||||
|
message,
|
||||||
|
'nick': attrs.nick,
|
||||||
|
'type': 'info'
|
||||||
|
};
|
||||||
|
this.createMessage(data);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1998,7 +2010,7 @@ converse.plugins.add('converse-muc', {
|
|||||||
|
|
||||||
if (await this.handleRetraction(attrs) ||
|
if (await this.handleRetraction(attrs) ||
|
||||||
await this.handleModeration(attrs) ||
|
await this.handleModeration(attrs) ||
|
||||||
this.subjectChangeHandled(attrs) ||
|
this.handleSubjectChange(attrs) ||
|
||||||
this.ignorableCSN(attrs)) {
|
this.ignorableCSN(attrs)) {
|
||||||
return api.trigger('message', {'stanza': original_stanza});
|
return api.trigger('message', {'stanza': original_stanza});
|
||||||
}
|
}
|
||||||
@ -2070,10 +2082,10 @@ converse.plugins.add('converse-muc', {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create info messages based on a received presence stanza
|
* Create info messages based on a received presence or message stanza
|
||||||
* @private
|
* @private
|
||||||
* @method _converse.ChatRoom#createInfoMessages
|
* @method _converse.ChatRoom#createInfoMessages
|
||||||
* @param { XMLElement } stanza: The presence stanza received
|
* @param { XMLElement } stanza
|
||||||
*/
|
*/
|
||||||
createInfoMessages (stanza) {
|
createInfoMessages (stanza) {
|
||||||
const is_self = stanza.querySelector("status[code='110']") !== null;
|
const is_self = stanza.querySelector("status[code='110']") !== null;
|
||||||
|
Loading…
Reference in New Issue
Block a user