2
0
Эх сурвалжийг харах

show headline messages in controlbox

Christoph Scholz 5 жил өмнө
parent
commit
a472a0806e

+ 1 - 0
CHANGES.md

@@ -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)
 

+ 4 - 0
sass/_controlbox.scss

@@ -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;

+ 73 - 0
spec/headline.js

@@ -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) {

+ 93 - 3
src/headless/converse-headlines.js

@@ -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 () {

+ 12 - 0
src/templates/headline_list.html

@@ -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>

+ 6 - 0
src/templates/headline_panel.html

@@ -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> -->