فهرست منبع

Refactoring of the headlines plugins

- Move template to relevant plugin
- Turn ElementView into CustomElement
- Use the terminology "Headlines Feed" instead of "Headlines Box"
- Break the `converse-headlines` plugin up into multiple files
- Fix CSS styling for headlines feeds for the Dracula theme
JC Brand 3 سال پیش
والد
کامیت
858a6051ac

+ 1 - 1
src/headless/headless.js

@@ -9,7 +9,7 @@ import "./plugins/caps/index.js";       // XEP-0115 Entity Capabilities
 import "./plugins/chat/index.js";       // RFC-6121 Instant messaging
 import "./plugins/chatboxes/index.js";
 import "./plugins/disco/index.js";      // XEP-0030 Service discovery
-import "./plugins/headlines.js";        // Support for headline messages
+import "./plugins/headlines/index.js";  // Support for headline messages
 import "./plugins/mam/index.js";        // XEP-0313 Message Archive Management
 import "./plugins/muc/index.js";        // XEP-0045 Multi-user chat
 import "./plugins/ping/index.js";       // XEP-0199 XMPP Ping

+ 0 - 164
src/headless/plugins/headlines.js

@@ -1,164 +0,0 @@
-/**
- * @module converse-headlines
- * @copyright 2022, the Converse.js contributors
- * @description XEP-0045 Multi-User Chat Views
- */
-import { _converse, api, converse } from "@converse/headless/core";
-import { isHeadline, isServerMessage } from '@converse/headless/shared/parsers';
-import { parseMessage } from '@converse/headless/plugins/chat/parsers';
-
-
-converse.plugins.add('converse-headlines', {
-    /* Plugin dependencies are other plugins which might be
-     * overridden or relied upon, and therefore need to be loaded before
-     * this plugin.
-     *
-     * If the setting "strict_plugin_dependencies" is set to true,
-     * an error will be raised if the plugin is not found. By default it's
-     * false, which means these plugins are only loaded opportunistically.
-     *
-     * NB: These plugins need to have already been loaded via require.js.
-     */
-    dependencies: ["converse-chat"],
-
-    overrides: {
-        // Overrides mentioned here will be picked up by converse.js's
-        // plugin architecture they will replace existing methods on the
-        // relevant objects or classes.
-        //
-        // New functions which don't exist yet can also be added.
-
-        ChatBoxes: {
-            model (attrs, options) {
-                const { _converse } = this.__super__;
-                if (attrs.type == _converse.HEADLINES_TYPE) {
-                    return new _converse.HeadlinesBox(attrs, options);
-                } else {
-                    return this.__super__.model.apply(this, arguments);
-                }
-            },
-        }
-    },
-
-
-    initialize () {
-        /* The initialize function gets called as soon as the plugin is
-         * loaded by converse.js's plugin machinery.
-         */
-
-        /**
-         * Shows headline messages
-         * @class
-         * @namespace _converse.HeadlinesBox
-         * @memberOf _converse
-         */
-        _converse.HeadlinesBox = _converse.ChatBox.extend({
-            defaults () {
-                return {
-                    'bookmarked': false,
-                    'hidden': ['mobile', 'fullscreen'].includes(api.settings.get("view_mode")),
-                    'message_type': 'headline',
-                    'num_unread': 0,
-                    'time_opened': this.get('time_opened') || (new Date()).getTime(),
-                    'type': _converse.HEADLINES_TYPE
-                }
-            },
-
-            async initialize () {
-                this.set({'box_id': `box-${this.get('jid')}`});
-                this.initUI();
-                this.initMessages();
-                await this.fetchMessages();
-                /**
-                 * Triggered once a {@link _converse.HeadlinesBox} has been created and initialized.
-                 * @event _converse#headlinesBoxInitialized
-                 * @type { _converse.HeadlinesBox }
-                 * @example _converse.api.listen.on('headlinesBoxInitialized', model => { ... });
-                 */
-                api.trigger('headlinesBoxInitialized', this);
-            }
-        });
-
-        async function onHeadlineMessage (stanza) {
-            // Handler method for all incoming messages of type "headline".
-            if (isHeadline(stanza) || isServerMessage(stanza)) {
-                const from_jid = stanza.getAttribute('from');
-
-                await api.waitUntil('rosterInitialized')
-                if (from_jid.includes('@') &&
-                        !_converse.roster.get(from_jid) &&
-                        !api.settings.get("allow_non_roster_messaging")) {
-                    return;
-                }
-                if (stanza.querySelector('body') === null) {
-                    // Avoid creating a chat box if we have nothing to show inside it.
-                    return;
-                }
-                const chatbox = _converse.chatboxes.create({
-                    'id': from_jid,
-                    'jid': from_jid,
-                    'type': _converse.HEADLINES_TYPE,
-                    'from': from_jid
-                });
-                const attrs = await parseMessage(stanza, _converse);
-                await chatbox.createMessage(attrs);
-                api.trigger('message', {chatbox, stanza, attrs});
-            }
-        }
-
-
-        /************************ BEGIN Event Handlers ************************/
-        function registerHeadlineHandler () {
-            _converse.connection.addHandler(message => (onHeadlineMessage(message) || true), null, 'message');
-        }
-        api.listen.on('connected', registerHeadlineHandler);
-        api.listen.on('reconnected', registerHeadlineHandler);
-        /************************ END Event Handlers ************************/
-
-
-        /************************ BEGIN API ************************/
-        Object.assign(api, {
-            /**
-             * The "headlines" namespace, which is used for headline-channels
-             * which are read-only channels containing messages of type
-             * "headline".
-             *
-             * @namespace api.headlines
-             * @memberOf api
-             */
-            headlines: {
-                /**
-                 * Retrieves a headline-channel or all headline-channels.
-                 *
-                 * @method api.headlines.get
-                 * @param {String|String[]} jids - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
-                 * @param {Object} [attrs] - Attributes to be set on the _converse.ChatBox model.
-                 * @param {Boolean} [create=false] - Whether the chat should be created if it's not found.
-                 * @returns { Promise<_converse.HeadlinesBox> }
-                 */
-                async get (jids, attrs={}, create=false) {
-                    async function _get (jid) {
-                        let model = await api.chatboxes.get(jid);
-                        if (!model && create) {
-                            model = await api.chatboxes.create(jid, attrs, _converse.HeadlinesBox);
-                        } else {
-                            model = (model && model.get('type') === _converse.HEADLINES_TYPE) ? model : null;
-                            if (model && Object.keys(attrs).length) {
-                                model.save(attrs);
-                            }
-                        }
-                        return model;
-                    }
-                    if (jids === undefined) {
-                        const chats = await api.chatboxes.get();
-                        return chats.filter(c => (c.get('type') === _converse.HEADLINES_TYPE));
-                    } else if (typeof jids === 'string') {
-                        return _get(jids);
-                    }
-                    return Promise.all(jids.map(jid => _get(jid)));
-                }
-            }
-        });
-        /************************ END API ************************/
-    }
-});

+ 44 - 0
src/headless/plugins/headlines/api.js

@@ -0,0 +1,44 @@
+import { _converse, api } from "@converse/headless/core";
+
+export default {
+    /**
+     * The "headlines" namespace, which is used for headline-channels
+     * which are read-only channels containing messages of type
+     * "headline".
+     *
+     * @namespace api.headlines
+     * @memberOf api
+     */
+    headlines: {
+        /**
+         * Retrieves a headline-channel or all headline-channels.
+         *
+         * @method api.headlines.get
+         * @param {String|String[]} jids - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
+         * @param {Object} [attrs] - Attributes to be set on the _converse.ChatBox model.
+         * @param {Boolean} [create=false] - Whether the chat should be created if it's not found.
+         * @returns { Promise<_converse.HeadlinesFeed> }
+         */
+        async get (jids, attrs={}, create=false) {
+            async function _get (jid) {
+                let model = await api.chatboxes.get(jid);
+                if (!model && create) {
+                    model = await api.chatboxes.create(jid, attrs, _converse.HeadlinesFeed);
+                } else {
+                    model = (model && model.get('type') === _converse.HEADLINES_TYPE) ? model : null;
+                    if (model && Object.keys(attrs).length) {
+                        model.save(attrs);
+                    }
+                }
+                return model;
+            }
+            if (jids === undefined) {
+                const chats = await api.chatboxes.get();
+                return chats.filter(c => (c.get('type') === _converse.HEADLINES_TYPE));
+            } else if (typeof jids === 'string') {
+                return _get(jids);
+            }
+            return Promise.all(jids.map(jid => _get(jid)));
+        }
+    }
+};

+ 31 - 0
src/headless/plugins/headlines/feed.js

@@ -0,0 +1,31 @@
+import ChatBox from '@converse/headless/plugins/chat/model.js';
+import { _converse, api } from '../../core.js';
+
+
+export default class HeadlinesFeed extends ChatBox {
+
+    defaults () {
+        return {
+            'bookmarked': false,
+            'hidden': ['mobile', 'fullscreen'].includes(api.settings.get("view_mode")),
+            'message_type': 'headline',
+            'num_unread': 0,
+            'time_opened': this.get('time_opened') || (new Date()).getTime(),
+            'type': _converse.HEADLINES_TYPE
+        }
+    }
+
+    async initialize () {
+        this.set({'box_id': `box-${this.get('jid')}`});
+        this.initUI();
+        this.initMessages();
+        await this.fetchMessages();
+        /**
+         * Triggered once a { @link _converse.HeadlinesFeed } has been created and initialized.
+         * @event _converse#headlinesFeedInitialized
+         * @type { _converse.HeadlinesFeed }
+         * @example _converse.api.listen.on('headlinesFeedInitialized', model => { ... });
+         */
+        api.trigger('headlinesFeedInitialized', this);
+    }
+}

+ 62 - 0
src/headless/plugins/headlines/index.js

@@ -0,0 +1,62 @@
+/**
+ * @module converse-headlines
+ * @copyright 2022, the Converse.js contributors
+ * @description XEP-0045 Multi-User Chat Views
+ */
+import HeadlinesFeed from './feed.js';
+import headlines_api from './api.js';
+import { _converse, api, converse } from "@converse/headless/core";
+import { onHeadlineMessage } from './utils.js';
+
+
+converse.plugins.add('converse-headlines', {
+    /* Plugin dependencies are other plugins which might be
+     * overridden or relied upon, and therefore need to be loaded before
+     * this plugin.
+     *
+     * If the setting "strict_plugin_dependencies" is set to true,
+     * an error will be raised if the plugin is not found. By default it's
+     * false, which means these plugins are only loaded opportunistically.
+     *
+     * NB: These plugins need to have already been loaded via require.js.
+     */
+    dependencies: ["converse-chat"],
+
+    overrides: {
+        // Overrides mentioned here will be picked up by converse.js's
+        // plugin architecture they will replace existing methods on the
+        // relevant objects or classes.
+        //
+        // New functions which don't exist yet can also be added.
+
+        ChatBoxes: {
+            model (attrs, options) {
+                const { _converse } = this.__super__;
+                if (attrs.type == _converse.HEADLINES_TYPE) {
+                    return new _converse.HeadlinesFeed(attrs, options);
+                } else {
+                    return this.__super__.model.apply(this, arguments);
+                }
+            },
+        }
+    },
+
+
+    initialize () {
+        /**
+         * Shows headline messages
+         * @class
+         * @namespace _converse.HeadlinesFeed
+         * @memberOf _converse
+         */
+        _converse.HeadlinesFeed = HeadlinesFeed;
+
+        function registerHeadlineHandler () {
+            _converse.connection.addHandler(m => (onHeadlineMessage(m) || true), null, 'message');
+        }
+        api.listen.on('connected', registerHeadlineHandler);
+        api.listen.on('reconnected', registerHeadlineHandler);
+
+        Object.assign(api, headlines_api);
+    }
+});

+ 33 - 0
src/headless/plugins/headlines/utils.js

@@ -0,0 +1,33 @@
+import { _converse, api } from "@converse/headless/core";
+import { isHeadline, isServerMessage } from '@converse/headless/shared/parsers';
+import { parseMessage } from '@converse/headless/plugins/chat/parsers';
+
+/**
+ * Handler method for all incoming messages of type "headline".
+ * @param { XMLElement } stanza
+ */
+export async function onHeadlineMessage (stanza) {
+    if (isHeadline(stanza) || isServerMessage(stanza)) {
+        const from_jid = stanza.getAttribute('from');
+
+        await api.waitUntil('rosterInitialized')
+        if (from_jid.includes('@') &&
+                !_converse.roster.get(from_jid) &&
+                !api.settings.get("allow_non_roster_messaging")) {
+            return;
+        }
+        if (stanza.querySelector('body') === null) {
+            // Avoid creating a chat box if we have nothing to show inside it.
+            return;
+        }
+        const chatbox = _converse.chatboxes.create({
+            'id': from_jid,
+            'jid': from_jid,
+            'type': _converse.HEADLINES_TYPE,
+            'from': from_jid
+        });
+        const attrs = await parseMessage(stanza, _converse);
+        await chatbox.createMessage(attrs);
+        api.trigger('message', {chatbox, stanza, attrs});
+    }
+}

+ 1 - 1
src/plugins/chatview/chat.js

@@ -26,7 +26,7 @@ export default class ChatView extends BaseChatView {
         /**
          * Triggered once the {@link _converse.ChatBoxView} has been initialized
          * @event _converse#chatBoxViewInitialized
-         * @type { _converse.HeadlinesBoxView }
+         * @type { _converse.ChatBoxView }
          * @example _converse.api.listen.on('chatBoxViewInitialized', view => { ... });
          */
         api.trigger('chatBoxViewInitialized', this);

+ 1 - 1
src/plugins/controlbox/templates/controlbox.js

@@ -38,7 +38,7 @@ export default (el) => {
                     ${o.connected
                         ? html`
                             <converse-user-profile></converse-user-profile>
-                            <converse-headlines-panel class="controlbox-section"></converse-headlines-panel>
+                            <converse-headlines-feeds-list class="controlbox-section"></converse-headlines-feeds-list>
                             <div id="chatrooms" class="controlbox-section">
                                 <converse-rooms-list></converse-rooms-list>
                                 <converse-bookmarks></converse-bookmarks>

+ 37 - 0
src/plugins/headlines-view/feed-list.js

@@ -0,0 +1,37 @@
+import tpl_feeds_list from './templates/feeds-list.js';
+import { CustomElement } from 'shared/components/element.js';
+import { _converse, api } from '@converse/headless/core';
+
+/**
+ * Custom element which renders a list of headline feeds
+ * @class
+ * @namespace _converse.HeadlinesFeedsList
+ * @memberOf _converse
+ */
+export class HeadlinesFeedsList extends CustomElement {
+
+    initialize () {
+        this.model = _converse.chatboxes;
+        this.listenTo(this.model, 'add', (m) => this.renderIfHeadline(m));
+        this.listenTo(this.model, 'remove', (m) => this.renderIfHeadline(m));
+        this.listenTo(this.model, 'destroy', (m) => this.renderIfHeadline(m));
+        this.requestUpdate();
+    }
+
+    render () {
+        return tpl_feeds_list(this);
+    }
+
+    renderIfHeadline (model) {
+        return model?.get('type') === _converse.HEADLINES_TYPE && this.requestUpdate();
+    }
+
+    async openHeadline (ev) { // eslint-disable-line class-methods-use-this
+        ev.preventDefault();
+        const jid = ev.target.getAttribute('data-headline-jid');
+        const feed = await api.headlines.get(jid);
+        feed.maybeShow(true);
+    }
+}
+
+api.elements.define('converse-headlines-feeds-list', HeadlinesFeedsList);

+ 5 - 2
src/plugins/headlines-view/index.js

@@ -5,7 +5,7 @@
  */
 import '../chatview/index.js';
 import './view.js';
-import { HeadlinesPanel } from './panel.js';
+import { HeadlinesFeedsList } from './feed-list.js';
 import { _converse, converse } from '@converse/headless/core';
 
 import './styles/headlines.scss';
@@ -25,6 +25,9 @@ converse.plugins.add('converse-headlines-view', {
     dependencies: ['converse-headlines', 'converse-chatview'],
 
     initialize () {
-        _converse.HeadlinesPanel = HeadlinesPanel;
+        _converse.HeadlinesFeedsList = HeadlinesFeedsList;
+
+        // Deprecated
+        _converse.HeadlinesPanel = HeadlinesFeedsList;
     }
 });

+ 0 - 45
src/plugins/headlines-view/panel.js

@@ -1,45 +0,0 @@
-import tpl_headline_panel from './templates/panel.js';
-import { ElementView } from '@converse/skeletor/src/element.js';
-import { __ } from 'i18n';
-import { _converse, api } from '@converse/headless/core';
-
-/**
- * View which renders headlines section of the control box.
- * @class
- * @namespace _converse.HeadlinesPanel
- * @memberOf _converse
- */
-export class HeadlinesPanel extends ElementView {
-    events = {
-        'click .open-headline': 'openHeadline'
-    }
-
-    initialize () {
-        this.model = _converse.chatboxes;
-        this.listenTo(this.model, 'add', this.renderIfHeadline);
-        this.listenTo(this.model, 'remove', this.renderIfHeadline);
-        this.listenTo(this.model, 'destroy', this.renderIfHeadline);
-        this.render();
-    }
-
-    toHTML () {
-        return tpl_headline_panel({
-            'heading_headline': __('Announcements'),
-            'headlineboxes': this.model.filter(m => m.get('type') === _converse.HEADLINES_TYPE),
-            'open_title': __('Click to open this server message')
-        });
-    }
-
-    renderIfHeadline (model) {
-        return model && model.get('type') === _converse.HEADLINES_TYPE && this.render();
-    }
-
-    openHeadline (ev) { // eslint-disable-line class-methods-use-this
-        ev.preventDefault();
-        const jid = ev.target.getAttribute('data-headline-jid');
-        const chat = _converse.chatboxes.get(jid);
-        chat.maybeShow(true);
-    }
-}
-
-api.elements.define('converse-headlines-panel', HeadlinesPanel);

+ 53 - 19
src/plugins/headlines-view/styles/headlines.scss

@@ -1,23 +1,50 @@
 .conversejs {
-    .chat-head-headline {
-        background-color: var(--headline-head-color);
-    }
+    .chatbox {
+        converse-headlines-heading {
+            &.chat-head {
+                .chatbox-title__text {
+                    color: var(--headline-head-text-color) !important;
+                    background-color: var(--headline-head-bg-color);
+                }
 
-    .chatbox.headlines {
-        .chat-head {
-            &.chat-head-chatbox {
-                background-color: var(--headline-head-color);
+                a, a:visited, a:hover, a:not([href]):not([tabindex]) {
+                    &.chatbox-btn {
+                        &.fa,
+                        &.fas,
+                        &.far {
+                            color: var(--headline-head-text-color);
+                            &.button-on:before {
+                                padding: 0.2em;
+                                background-color: var(--headline-head-text-color);
+                                color: var(--headline-head-bg-color);
+                            }
+                        }
+                    }
+                }
             }
         }
-        .chat-body {
-            background-color: var(--headline-head-color);
-            .chat-message {
-                color: var(--headline-message-color);
+
+        &.headlines {
+            .chat-head {
+                &.chat-head-chatbox {
+                    background-color: var(--headline-head-bg-color);
+                    border-bottom: var(--headline-head-border-bottom);
+                }
+            }
+            .chat-body {
+                background-color: var(--background);
+                .chat-message {
+                    color: var(--headline-message-color);
+                }
+                hr {
+                    border-bottom: var(--headline-separator-border-bottom);
+                }
+            }
+            .chat-content {
+                height: 100%;
             }
         }
-        .chat-content {
-            height: 100%;
-        }
+
     }
 
     .message {
@@ -29,22 +56,29 @@
             }
         }
     }
-}
 
-.conversejs {
+    #controlbox {
+        .controlbox-section {
+            .controlbox-heading--headline {
+                color: var(--headline-head-text-color);
+            }
+        }
+    }
+
+
     converse-chats {
         &.converse-fullscreen {
             .chatbox.headlines {
                 .box-flyout {
-                    background-color: var(--headline-head-color);
+                    background-color: var(--headline-head-text-color);
                 }
                 .chat-head {
                     &.chat-head-chatbox {
-                        background-color: var(--headline-head-color);
+                        background-color: var(--headline-head-text-color);
                     }
                 }
                 .flyout {
-                    border-color: var(--headline-head-color);
+                    border-color: var(--headline-head-text-color);
                 }
             }
         }

+ 33 - 0
src/plugins/headlines-view/templates/feeds-list.js

@@ -0,0 +1,33 @@
+import { __ } from 'i18n';
+import { _converse } from '@converse/headless/core';
+import { html } from "lit";
+
+const tpls_headlines_feeds_list_item = (el, feed) => {
+    const open_title = __('Click to open this server message');
+    return html`
+        <div class="list-item controlbox-padded d-flex flex-row"
+            data-headline-jid="${feed.get('jid')}">
+        <a class="list-item-link open-headline available-room w-100"
+            data-headline-jid="${feed.get('jid')}"
+            title="${open_title}"
+            @click=${ev => el.openHeadline(ev)}
+            href="#">${feed.get('jid')}</a>
+        </div>
+    `;
+}
+
+export default (el) => {
+    const feeds = el.model.filter(m => m.get('type') === _converse.HEADLINES_TYPE);
+    const heading_headline  = __('Announcements');
+    return html`
+        <div class="controlbox-section" id="headline">
+            <div class="d-flex controlbox-padded ${ feeds.length ? '' : 'hidden' }">
+                <span class="w-100 controlbox-heading controlbox-heading--headline">${heading_headline}</span>
+            </div>
+        </div>
+        <div class="list-container list-container--headline ${ feeds.length ? '' : 'hidden' }">
+            <div class="items-list rooms-list headline-list">
+                ${ feeds.map(feed => tpls_headlines_feeds_list_item(el, feed)) }
+            </div>
+        </div>`
+}

+ 0 - 12
src/plugins/headlines-view/templates/panel.js

@@ -1,12 +0,0 @@
-import { html } from "lit";
-import tpl_headline_list from "templates/headline_list.js";
-
-
-export default (o) => html`
-    <div class="controlbox-section" id="headline">
-        <div class="d-flex controlbox-padded ${ o.headlineboxes.length ? '' : 'hidden' }">
-            <span class="w-100 controlbox-heading controlbox-heading--headline">${o.heading_headline}</span>
-        </div>
-    </div>
-    ${ tpl_headline_list(o) }
-`;

+ 6 - 1
src/plugins/headlines-view/tests/headline.js

@@ -68,7 +68,12 @@ describe("A headlines box", function () {
     it("will show headline messages in the controlbox", mock.initConverse(
             [], {}, async function (_converse) {
 
-        await mock.waitForRoster(_converse, 'current', 0);
+        await mock.waitForRoster(_converse, 'current', 1);
+        await mock.openControlBox(_converse);
+
+            const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
+            await mock.openChatBoxFor(_converse, sender_jid);
+
         const { u, $msg} = converse.env;
         /* <message from='notify.example.com'
          *          to='romeo@im.example.com'

+ 4 - 4
src/plugins/headlines-view/view.js

@@ -3,7 +3,7 @@ import tpl_headlines from './templates/headlines.js';
 import { _converse, api } from '@converse/headless/core';
 
 
-class HeadlinesView extends BaseChatView {
+class HeadlinesFeedView extends BaseChatView {
 
     async initialize() {
         _converse.chatboxviews.add(this.jid, this);
@@ -20,9 +20,9 @@ class HeadlinesView extends BaseChatView {
         await this.model.messages.fetched;
         this.model.maybeShow();
         /**
-         * Triggered once the {@link _converse.HeadlinesBoxView} has been initialized
+         * Triggered once the { @link _converse.HeadlinesFeedView } has been initialized
          * @event _converse#headlinesBoxViewInitialized
-         * @type { _converse.HeadlinesBoxView }
+         * @type { _converse.HeadlinesFeedView }
          * @example _converse.api.listen.on('headlinesBoxViewInitialized', view => { ... });
          */
         api.trigger('headlinesBoxViewInitialized', this);
@@ -52,4 +52,4 @@ class HeadlinesView extends BaseChatView {
     }
 }
 
-api.elements.define('converse-headlines', HeadlinesView);
+api.elements.define('converse-headlines', HeadlinesFeedView);

+ 1 - 1
src/plugins/minimize/utils.js

@@ -58,7 +58,7 @@ function getBoxesWidth (newchat) {
  * to create space.
  * @private
  * @method _converse.ChatBoxViews#trimChats
- * @param { _converse.ChatBoxView|_converse.ChatRoomView|_converse.ControlBoxView|_converse.HeadlinesBoxView } [newchat]
+ * @param { _converse.ChatBoxView|_converse.ChatRoomView|_converse.ControlBoxView|_converse.HeadlinesFeedView } [newchat]
  */
 export function trimChats (newchat) {
     if (_converse.isTestEnv() || api.settings.get('no_trimming') || api.settings.get("view_mode") !== 'overlayed') {

+ 4 - 1
src/shared/styles/themes/classic.scss

@@ -131,8 +131,11 @@
     --muc-toolbar-btn-color: var(--redder-orange);
     --muc-toolbar-btn-disabled-color: gray;
 
-    --headline-head-color: var(--orange);
+    --headlines-color: var(--orange);
+    --headline-head-text-color: var(--white);
+    --headline-head-bg-color: var(--headlines-color);
     --headline-message-color: #D2842B;
+    --headline-separator-border-bottom: 2px solid var(--headlines-color);
 
     --chatbox-button-size: 14px;
     --fullpage-chatbox-button-size: 16px;

+ 7 - 0
src/shared/styles/themes/dracula.scss

@@ -23,6 +23,13 @@
 
     // ---
 
+    --headlines-color: var(--pink);
+    --headline-head-text-color: var(--headlines-color);
+    --headline-head-bg-color: var(--background);
+    --headline-message-color: var(--headlines-color);
+    --headline-separator-border-bottom: 2px solid var(--headlines-color);
+    --headline-head-border-bottom: 0.15em solid var(--headlines-color);
+
     --icon-hover-color: var(--cyan);
     --gray-color: var(--comment);
 

+ 0 - 19
src/templates/headline_list.js

@@ -1,19 +0,0 @@
-import { html } from "lit";
-
-const tpl_headline_box = (o) => html`
-    <div class="list-item controlbox-padded d-flex flex-row"
-        data-headline-jid="${o.headlinebox.get('jid')}">
-    <a class="list-item-link open-headline available-room w-100"
-        data-headline-jid="${o.headlinebox.get('jid')}"
-        title="${o.open_title}" href="#">${o.headlinebox.get('jid')}</a>
-    </div>
-`;
-
-
-export default (o) => html`
-    <div class="list-container list-container--headline ${ o.headlineboxes.length ? '' : 'hidden' }">
-        <div class="items-list rooms-list headline-list">
-            ${ o.headlineboxes.map(headlinebox => tpl_headline_box(Object.assign({headlinebox}, o))) }
-        </div>
-    </div>
-`;