show headline messages in controlbox

This commit is contained in:
Christoph Scholz 2020-01-22 09:22:38 +01:00 committed by JC Brand
parent 464c68a3b6
commit a472a0806e
6 changed files with 189 additions and 3 deletions

View File

@ -10,6 +10,7 @@
- #1823: New config options [muc_roomid_policy](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy)
and [muc_roomid_policy_hint](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy-hint)
- #1826: A user can now add himself as a contact
- #1839: Headline messages are shown in controlbox
## 6.0.0 (2020-01-09)

View File

@ -230,6 +230,10 @@
color: var(--chat-head-color-dark);
}
.controlbox-heading--headline {
color: var(--headline-head-color);
}
.controlbox-heading__btn {
cursor: pointer;
font-size: 1em;

View File

@ -87,6 +87,79 @@
done();
}));
it("will show headline messages in the controlbox", mock.initConverse(
['rosterGroupsFetched'], {}, async function (done, _converse) {
/* <message from='notify.example.com'
* to='romeo@im.example.com'
* type='headline'
* xml:lang='en'>
* <subject>SIEVE</subject>
* <body>&lt;juliet@example.com&gt; You got mail.</body>
* <x xmlns='jabber:x:oob'>
* <url>
* imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18
* </url>
* </x>
* </message>
*/
const stanza = $msg({
'type': 'headline',
'from': 'notify.example.com',
'to': 'romeo@montague.lit',
'xml:lang': 'en'
})
.c('subject').t('SIEVE').up()
.c('body').t('&lt;juliet@example.com&gt; You got mail.').up()
.c('x', {'xmlns': 'jabber:x:oob'})
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
const view = _converse.chatboxviews.get('controlbox');
await u.waitUntil(() => view.el.querySelectorAll(".open-headline").length);
expect(view.el.querySelectorAll('.open-headline').length).toBe(1);
expect(view.el.querySelector('.open-headline').text).toBe('notify.example.com');
done();
}));
it("will remove headline messages from the controlbox if closed", mock.initConverse(
['rosterGroupsFetched'], {}, async function (done, _converse) {
/* <message from='notify.example.com'
* to='romeo@im.example.com'
* type='headline'
* xml:lang='en'>
* <subject>SIEVE</subject>
* <body>&lt;juliet@example.com&gt; You got mail.</body>
* <x xmlns='jabber:x:oob'>
* <url>
* imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18
* </url>
* </x>
* </message>
*/
const stanza = $msg({
'type': 'headline',
'from': 'notify.example.com',
'to': 'romeo@montague.lit',
'xml:lang': 'en'
})
.c('subject').t('SIEVE').up()
.c('body').t('&lt;juliet@example.com&gt; You got mail.').up()
.c('x', {'xmlns': 'jabber:x:oob'})
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
const cbview = _converse.chatboxviews.get('controlbox');
await u.waitUntil(() => cbview.el.querySelectorAll(".open-headline").length);
const hlview = _converse.chatboxviews.get('notify.example.com');
const close_el = hlview.el.querySelector('.close-chatbox-button');
close_el.click();
await u.waitUntil(() => cbview.el.querySelectorAll(".open-headline").length === 0);
expect(cbview.el.querySelectorAll('.open-headline').length).toBe(0);
done();
}));
it("will not show a headline messages from a full JID if allow_non_roster_messaging is false",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {}, function (done, _converse) {

View File

@ -9,8 +9,10 @@
import "converse-chatview";
import converse from "@converse/headless/converse-core";
import { isString } from "lodash";
import tpl_headline_list from "templates/headline_list.html";
import tpl_headline_panel from "templates/headline_panel.html";
const { utils } = converse.env;
const { Backbone, utils } = converse.env;
converse.plugins.add('converse-headlines', {
@ -42,7 +44,13 @@ converse.plugins.add('converse-headlines', {
return this.__super__.model.apply(this, arguments);
}
},
}
},
ControlBoxView: {
renderControlBoxPane () {
this.__super__.renderControlBoxPane.apply(this, arguments);
this.renderHeadlinePanel();
},
},
},
@ -50,7 +58,33 @@ converse.plugins.add('converse-headlines', {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this;
const { _converse } = this,
{ __ } = _converse;
const viewWithHeadlinePanel = {
renderHeadlinePanel () {
if (this.headlinepanel && utils.isInDOM(this.headlinepanel.el)) {
return this.headlinepanel;
}
this.headlinepanel = new _converse.HeadlinePanel();
this.el.querySelector('.controlbox-pane').insertAdjacentElement(
'beforeEnd', this.headlinepanel.render().el);
return this.headlinepanel;
},
getHeadlinePanel () {
if (this.headlinepanel && utils.isInDOM(this.headlinepanel.el)) {
return this.headlinepanel;
} else {
return this.renderHeadlinePanel();
}
}
}
if (_converse.ControlBoxView) {
Object.assign(_converse.ControlBoxView.prototype, viewWithHeadlinePanel);
}
/**
* Shows headline messages
@ -83,6 +117,26 @@ converse.plugins.add('converse-headlines', {
}
});
function getAllHeadlineBoxes (removedBox = null) {
const chatboxviews = _converse.chatboxviews.getAll();
return Object.keys(chatboxviews)
.filter(
id => chatboxviews[id].el.classList.contains('headlines') &&
id !== removedBox
);
}
function renderHeadlineList (removedBox = null) {
const controlboxview = _converse.chatboxviews.get('controlbox');
if (controlboxview !== undefined) {
const el = controlboxview.el.querySelector('.list-container--headline');
const headline_list = tpl_headline_list({
'headlineboxes': getAllHeadlineBoxes(removedBox),
'open_title': __('Click to open this server message'),
});
el && (el.outerHTML = headline_list);
}
}
async function onHeadlineMessage (message) {
// Handler method for all incoming messages of type "headline".
@ -106,9 +160,45 @@ converse.plugins.add('converse-headlines', {
const attrs = await chatbox.getMessageAttributesFromStanza(message, message);
await chatbox.messages.create(attrs);
_converse.api.trigger('message', {'chatbox': chatbox, 'stanza': message});
renderHeadlineList();
_converse.chatboxviews.get(from_jid).el
.querySelector('.close-chatbox-button')
.addEventListener("click",
() => renderHeadlineList(from_jid)
);
}
}
/**
* Backbone.NativeView which renders headlines section of the control box.
* @class
* @namespace _converse.HeadlinePanel
* @memberOf _converse
*/
_converse.HeadlinePanel = Backbone.NativeView.extend({
tagName: 'div',
className: 'controlbox-section',
id: 'headline',
events: {
'click .open-headline': 'openHeadline'
},
openHeadline (ev) {
ev.preventDefault();
const jid = ev.target.getAttribute('data-headline-jid');
const chat = _converse.chatboxes.get(jid);
chat.maybeShow(true);
},
render () {
this.el.innerHTML = tpl_headline_panel({
'heading_headline': __('Server Messages')
});
return this;
}
});
/************************ BEGIN Event Handlers ************************/
function registerHeadlineHandler () {

View File

@ -0,0 +1,12 @@
<div class="list-container list-container--headline {{{ !o.headlineboxes.length && 'hidden' || '' }}}">
<div class="items-list rooms-list headline-list">
{[o.headlineboxes.forEach(function (headline) { ]}
<div class="list-item controlbox-padded d-flex flex-row"
data-headline-jid="{{{headline}}}">
<a class="list-item-link open-headline available-room w-100"
data-headline-jid="{{{headline}}}"
title="{{{o.open_title}}}" href="#">{{{headline}}}</a>
</div>
{[ }) ]}
</div>
</div>

View File

@ -0,0 +1,6 @@
<!-- <div id="headline"> -->
<div class="d-flex controlbox-padded">
<span class="w-100 controlbox-heading controlbox-heading--headline">{{{o.heading_headline}}}</span>
</div>
<div class="list-container list-container--headline"></div>
<!-- </div> -->