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
This commit is contained in:
parent
52693bfc0b
commit
858a6051ac
|
@ -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
|
||||
|
|
|
@ -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
src/headless/plugins/headlines/api.js
Normal file
44
src/headless/plugins/headlines/api.js
Normal file
|
@ -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
src/headless/plugins/headlines/feed.js
Normal file
31
src/headless/plugins/headlines/feed.js
Normal file
|
@ -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
src/headless/plugins/headlines/index.js
Normal file
62
src/headless/plugins/headlines/index.js
Normal file
|
@ -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
src/headless/plugins/headlines/utils.js
Normal file
33
src/headless/plugins/headlines/utils.js
Normal file
|
@ -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});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
src/plugins/headlines-view/feed-list.js
Normal file
37
src/plugins/headlines-view/feed-list.js
Normal file
|
@ -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,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;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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);
|
|
@ -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
src/plugins/headlines-view/templates/feeds-list.js
Normal file
33
src/plugins/headlines-view/templates/feeds-list.js
Normal file
|
@ -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>`
|
||||
}
|
|
@ -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) }
|
||||
`;
|
|
@ -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'
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user