Commit 879e165a authored by JC Brand's avatar JC Brand

Refactoring

- Move headless one-on-one chat functionality into converse-chat
- Split converse-headline into converse-headlines and converse-headlines-views
- Add api in `_converse.api.chatboxes` for creating chatboxes
- Add `_converse.api.controlbox.get` method
parent 93d56898
......@@ -14,6 +14,7 @@
instances. Still working out a wire protocol for compatibility with other clients.
To add custom emojis, edit the `emojis.json` file.
- Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`.
- New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get)
### Breaking changes
......@@ -34,10 +35,12 @@
* `_converse.api.rooms.create`
* `_converse.api.roomviews.close`
- `_converse.api.chats.get()` now only returns one-on-one chats, not the control box or headline notifications.
- The `show_only_online_users` setting has been removed.
- The order of certain events have now changed: `statusInitialized` is now triggered after `initialized` and `connected` and `reconnected`.
- `_converse.api.alert.show` is now `_converse.api.show` and instead of taking
an integer for the `type`, "info", "warn" or "error" should be passed in.
- The `converse-headline` plugin has been split up into `converse-headlines` and `converse-headlines-view`.
## 5.0.4 (2019-10-08)
- New config option [allow_message_corrections](https://conversejs.org/docs/html/configuration.html#allow-message-corrections)
......
......@@ -168,7 +168,7 @@
'name': 'The Play',
'nick': ' Othello'
});
await u.waitUntil(() => _converse.api.rooms.get().length);
await new Promise(resolve => _converse.api.listen.once('chatBoxInitialized', resolve));
expect(_.isUndefined(_converse.chatboxviews.get(jid))).toBeFalsy();
// Check that we don't auto-join if muc_respect_autojoin is false
......
This diff is collapsed.
......@@ -88,7 +88,7 @@
id: (new Date()).getTime()
}).c('body').t('hello').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg);
_converse.handleMessageStanza(msg);
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll(".msgs-indicator").length);
spyOn(chatview.model, 'incrementUnreadMsgCounter').and.callThrough();
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('1');
......@@ -101,7 +101,7 @@
id: (new Date()).getTime()
}).c('body').t('hello again').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg);
_converse.handleMessageStanza(msg);
await u.waitUntil(() => chatview.model.incrementUnreadMsgCounter.calls.count());
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count').textContent).toBe('2');
expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('2');
......
......@@ -269,7 +269,7 @@
// Test on chat that's not open
chat = await _converse.api.chats.get(jid);
expect(typeof chat === 'undefined').toBeTruthy();
expect(chat === null).toBeTruthy();
expect(_converse.chatboxes.length).toBe(1);
// Test for one JID
......@@ -281,7 +281,7 @@
await u.waitUntil(() => u.isVisible(view.el));
// Test for multiple JIDs
test_utils.openChatBoxFor(_converse, jid2);
await u.waitUntil(() => _converse.chatboxes.length == 2);
await u.waitUntil(() => _converse.chatboxes.length == 3);
const list = await _converse.api.chats.get([jid, jid2]);
expect(Array.isArray(list)).toBeTruthy();
expect(list[0].get('box_id')).toBe(`box-${btoa(jid)}`);
......
......@@ -163,7 +163,7 @@
await test_utils.waitForRoster(_converse, 'current');
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
......@@ -177,7 +177,7 @@
let message = chat_content.querySelector('.chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
......
......@@ -14,7 +14,7 @@
it("will not open nor display non-headline messages",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {}, async function (done, _converse) {
['rosterGroupsFetched', 'chatBoxesFetched'], {}, function (done, _converse) {
/* XMPP spam message:
*
......@@ -36,9 +36,9 @@
.c('nick', {'xmlns': "http://jabber.org/protocol/nick"}).t("-wwdmz").up()
.c('body').t('SORRY FOR THIS ADVERT');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => _converse.api.chats.get().length);
expect(u.isHeadlineMessage.called).toBeTruthy();
expect(u.isHeadlineMessage.returned(false)).toBeTruthy();
expect(_converse.api.headlines.get().length === 0);
u.isHeadlineMessage.restore();
done();
}));
......
......@@ -205,7 +205,7 @@
describe("An archived message", function () {
describe("when recieved", function () {
describe("when received", function () {
it("is discarded if it doesn't come from the right sender",
mock.initConverse(
......
This diff is collapsed.
......@@ -95,7 +95,7 @@
id: (new Date()).getTime()
}).c('body').t('This message is sent to a minimized chatbox').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg);
_converse.handleMessageStanza(msg);
}
return u.waitUntil(() => chatview.model.messages.length);
}).then(() => {
......@@ -103,7 +103,7 @@
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((3).toString());
// Chat state notifications don't increment the unread messages counter
// <composing> state
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
from: contact_jid,
to: _converse.connection.jid,
type: 'chat',
......@@ -112,7 +112,7 @@
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <paused> state
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
from: contact_jid,
to: _converse.connection.jid,
type: 'chat',
......@@ -121,7 +121,7 @@
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <gone> state
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
from: contact_jid,
to: _converse.connection.jid,
type: 'chat',
......@@ -130,7 +130,7 @@
expect(_converse.minimized_chats.toggleview.el.querySelector('.unread-message-count').textContent).toBe((i).toString());
// <inactive> state
_converse.chatboxes.onMessage($msg({
_converse.handleMessageStanza($msg({
from: contact_jid,
to: _converse.connection.jid,
type: 'chat',
......
......@@ -89,7 +89,7 @@
// Non-existing room
muc_jid = 'chillout2@montague.lit';
room = await _converse.api.rooms.get(muc_jid);
expect(typeof room === 'undefined').toBeTruthy();
expect(room).toBe(null);
done();
}));
......
......@@ -120,7 +120,6 @@
by="room@muc.example.com"/>
</message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => _converse.api.chats.get().length);
await u.waitUntil(() => view.model.messages.length === 1);
await u.waitUntil(() => view.model.findDuplicateFromStanzaID.calls.count() === 1);
let result = await view.model.findDuplicateFromStanzaID.calls.all()[0].returnValue;
......@@ -572,7 +571,6 @@
const view = _converse.api.chatviews.get(muc_jid);
view.model.sendMessage('hello world');
await u.waitUntil(() => _converse.api.chats.get().length);
await u.waitUntil(() => view.model.messages.length === 1);
const msg = view.model.messages.at(0);
expect(msg.get('stanza_id')).toBeUndefined();
......
......@@ -30,7 +30,7 @@
id: (new Date()).getTime()
}).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
await _converse.chatboxes.onMessage(msg); // This will emit 'message'
await _converse.handleMessageStanza(msg); // This will emit 'message'
await u.waitUntil(() => _converse.api.chatviews.get(sender_jid));
expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
expect(_converse.showMessageNotification).toHaveBeenCalled();
......
......@@ -303,7 +303,6 @@
spyOn(registerview, 'onRegistrationFields').and.callThrough();
spyOn(registerview, 'renderRegistrationForm').and.callThrough();
registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(_converse.connection, 'connect').and.callThrough();
registerview.el.querySelector('input[name=domain]').value = 'conversejs.org';
registerview.el.querySelector('input[type=submit]').click();
......
......@@ -263,7 +263,7 @@
expect(window.confirm).toHaveBeenCalledWith(
'Are you sure you want to leave the groupchat lounge@conference.shakespeare.lit?');
await u.waitUntil(() => !_converse.api.rooms.get().length);
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(0);
expect(_converse.chatboxes.length).toBe(1);
......
......@@ -34,8 +34,8 @@
'xmlns': 'urn:xmpp:spoiler:0',
}).t(spoiler_hint)
.tree();
await _converse.chatboxes.onMessage(msg);
await u.waitUntil(() => _converse.api.chats.get().length === 2);
_converse.connection._dataRecv(test_utils.createRequest(msg));
await new Promise(resolve => _converse.api.listen.once('chatBoxInitialized', resolve));
const view = _converse.chatboxviews.get(sender_jid);
await new Promise(resolve => view.once('messageInserted', resolve));
await u.waitUntil(() => view.model.vcard.get('fullname') === 'Mercutio')
......@@ -69,10 +69,10 @@
.c('spoiler', {
'xmlns': 'urn:xmpp:spoiler:0',
}).tree();
await _converse.chatboxes.onMessage(msg);
await u.waitUntil(() => _converse.api.chats.get().length === 2);
_converse.connection._dataRecv(test_utils.createRequest(msg));
await new Promise(resolve => _converse.api.listen.once('chatBoxInitialized', resolve));
const view = _converse.chatboxviews.get(sender_jid);
await new Promise(resolve => view.once('messageInserted', resolve));
await u.waitUntil(() => u.isVisible(view.el));
await u.waitUntil(() => view.model.vcard.get('fullname') === 'Mercutio')
expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, 'Mercutio')).toBeTruthy();
const message_content = view.el.querySelector('.chat-msg__text');
......
......@@ -47,6 +47,7 @@ converse.plugins.add('converse-chatview', {
*/
dependencies: [
"converse-chatboxviews",
"converse-chat",
"converse-disco",
"converse-message-view",
"converse-modal"
......@@ -72,17 +73,6 @@ converse.plugins.add('converse-chatview', {
},
});
function onWindowStateChanged (data) {
if (_converse.chatboxviews) {
_converse.chatboxviews.forEach(view => {
if (view.model.get('id') !== 'controlbox') {
view.onWindowStateChanged(data.state);
}
});
}
}
_converse.api.listen.on('windowStateChanged', onWindowStateChanged);
_converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({
initialize () {
......@@ -92,6 +82,9 @@ converse.plugins.add('converse-chatview', {
if (this.model.vcard) {
this.listenTo(this.model.vcard, 'change', this.debouncedRender);
}
if (this.model.contact) {
this.listenTo(this.model.contact, 'destroy', this.debouncedRender);
}
if (this.model.rosterContactAdded) {
this.model.rosterContactAdded.then(() => {
this.listenTo(this.model.contact, 'change:nickname', this.debouncedRender);
......@@ -101,8 +94,8 @@ converse.plugins.add('converse-chatview', {
},
render () {
const vcard = get(this.model, 'vcard'),
vcard_json = vcard ? vcard.toJSON() : {};
const vcard = get(this.model, 'vcard');
const vcard_json = vcard ? vcard.toJSON() : {};
this.el.innerHTML = tpl_chatbox_head(
Object.assign(
vcard_json,
......@@ -409,10 +402,6 @@ converse.plugins.add('converse-chatview', {
this.heading = new _converse.ChatBoxHeading({'model': this.model});
this.heading.render();
this.heading.chatview = this;
if (this.model.contact !== undefined) {
this.listenTo(this.model.contact, 'destroy', this.heading.render);
}
const flyout = this.el.querySelector('.flyout');
flyout.insertBefore(this.heading.el, flyout.querySelector('.chat-body'));
return this;
......@@ -1299,15 +1288,29 @@ converse.plugins.add('converse-chatview', {
_converse.api.listen.on('chatBoxViewsInitialized', () => {
const views = _converse.chatboxviews;
_converse.chatboxes.on('add', item => {
_converse.chatboxes.on('add', async item => {
if (!views.get(item.get('id')) && item.get('type') === _converse.PRIVATE_CHAT_TYPE) {
await item.initialized;
views.add(item.get('id'), new _converse.ChatBoxView({model: item}));
}
});
});
// Advertise that we support XEP-0382 Message Spoilers
/************************ BEGIN Event Handlers ************************/
function onWindowStateChanged (data) {
if (_converse.chatboxviews) {
_converse.chatboxviews.forEach(view => {
if (view.model.get('id') !== 'controlbox') {
view.onWindowStateChanged(data.state);
}
});
}
}
_converse.api.listen.on('windowStateChanged', onWindowStateChanged);
_converse.api.listen.on('connected', () => _converse.api.disco.own.features.add(Strophe.NS.SPOILER));
/************************ END Event Handlers ************************/
/************************ BEGIN API ************************/
Object.assign(_converse.api, {
......
......@@ -69,7 +69,7 @@ converse.plugins.add('converse-controlbox', {
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-modal", "converse-chatboxes", "converse-rosterview", "converse-chatview"],
dependencies: ["converse-modal", "converse-chatboxes", "converse-chat", "converse-rosterview", "converse-chatview"],
enabled (_converse) {
return !_converse.singleton;
......@@ -626,16 +626,25 @@ converse.plugins.add('converse-controlbox', {
* @namespace _converse.api.controlbox
* @memberOf _converse.api
*/
'controlbox': {
controlbox: {
/**
* Retrieves the controlbox view.
*
* Opens the controlbox
* @method _converse.api.controlbox.open
* @returns { Promise<_converse.ControlBox> }
*/
async open () {
await _converse.api.waitUntil('chatBoxesFetched');
const model = await _converse.api.chatboxes.get('controlbox') ||
_converse.api.chatboxes.create('controlbox', {}, _converse.Controlbox);
model.trigger('show');
return model;
},
/**
* Returns the controlbox view.
* @method _converse.api.controlbox.get
*
* @example
* const view = _converse.api.controlbox.get();
*
* @returns {Backbone.View} View representing the controlbox
* @returns { Backbone.View } View representing the controlbox
* @example const view = _converse.api.controlbox.get();
*/
get () {
return _converse.chatboxviews.get('controlbox');
......
// Converse.js (A browser based XMPP chat client)
// https://conversejs.org
//
// Copyright (c) 2019, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
/**
* @module converse-headline
*/
import "converse-chatview";
import converse from "@converse/headless/converse-core";
import tpl_chatbox from "templates/chatbox.html";
converse.plugins.add('converse-headlines-view', {
/* 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-headlines", "converse-chatview"],
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this;
_converse.HeadlinesBoxView = _converse.ChatBoxView.extend({
className: 'chatbox headlines',
events: {
'click .close-chatbox-button': 'close',
'click .toggle-chatbox-button': 'minimize',
'keypress textarea.chat-textarea': 'onKeyDown'
},
initialize () {
this.initDebounced();
this.model.disable_mam = true; // Don't do MAM queries for this box
this.listenTo(this.model.messages, 'add', this.onMessageAdded);
this.listenTo(this.model, 'show', this.show);
this.listenTo(this.model, 'destroy', this.hide);
this.listenTo(this.model, 'change:minimized', this.onMinimizedChanged);
this.render().insertHeading()
this.updateAfterMessagesFetched();
this.insertIntoDOM().hide();
_converse.api.trigger('chatBoxInitialized', this);
},
render () {
this.el.setAttribute('id', this.model.get('box_id'))
this.el.innerHTML = tpl_chatbox(
Object.assign(this.model.toJSON(), {
info_close: '',
label_personal_message: '',
show_send_button: false,
show_toolbar: false,
unread_msgs: ''
}
));
this.content = this.el.querySelector('.chat-content');
return this;
},
// Override to avoid the methods in converse-chatview.js
'renderMessageForm': function renderMessageForm () {},
'afterShown': function afterShown () {}
});
_converse.api.listen.on('chatBoxViewsInitialized', () => {
const views = _converse.chatboxviews;
_converse.chatboxes.on('add', item => {
if (!views.get(item.get('id')) && item.get('type') === _converse.HEADLINES_TYPE) {
views.add(item.get('id'), new _converse.HeadlinesBoxView({model: item}));
}
});
});
}
});
......@@ -112,8 +112,9 @@ converse.plugins.add('converse-minimize', {
ChatBoxHeading: {
render () {
const { _converse } = this.__super__,
{ __ } = _converse;
const { _converse } = this.__super__;
const { __ } = _converse;
this.__super__.render.apply(this, arguments);
const new_html = tpl_chatbox_minimize({
'info_minimize': __('Minimize this chat box')
......
......@@ -91,7 +91,7 @@ converse.plugins.add('converse-roomslist', {
toHTML () {
return tpl_rooms_list({
'rooms': _converse.api.rooms.get(),
'rooms': this.model.filter(m => m.get('type') === _converse.CHATROOMS_TYPE),
'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
'collapsed': this.list_model.get('toggle-state') !== _converse.OPENED,
'desc_rooms': __('Click to toggle the list of open groupchats'),
......
......@@ -17,10 +17,10 @@ import "converse-controlbox"; // The control box
import "converse-dragresize"; // Allows chat boxes to be resized by dragging them
import "converse-emoji-views";
import "converse-fullscreen";
import "converse-headline"; // Support for headline messages
import "converse-mam-views";
import "converse-minimize"; // Allows chat boxes to be minimized
import "converse-muc-views"; // Views related to MUC
import "converse-headlines-view";
import "converse-notification"; // HTML5 Notifications
import "converse-omemo";
import "converse-profile";
......@@ -51,6 +51,7 @@ const WHITELISTED_PLUGINS = [
'converse-minimize',
'converse-modal',
'converse-muc-views',
'converse-headlines-view',
'converse-notification',
'converse-omemo',
'converse-profile',
......
This diff is collapsed.
This diff is collapsed.
......@@ -78,10 +78,12 @@ const CORE_PLUGINS = [
'converse-bosh',
'converse-caps',
'converse-chatboxes',
'converse-chat',
'converse-disco',
'converse-emoji',
'converse-mam',
'converse-muc',
'converse-headlines',
'converse-ping',
'converse-pubsub',
'converse-roster',
......
......@@ -8,12 +8,12 @@
*/
import "converse-chatview";
import converse from "@converse/headless/converse-core";
import tpl_chatbox from "templates/chatbox.html";
import { isString } from "lodash";
const { utils } = converse.env;
converse.plugins.add('converse-headline', {
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.
......@@ -24,7 +24,7 @@ converse.plugins.add('converse-headline', {
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-chatview"],
dependencies: ["converse-chat"],
overrides: {
// Overrides mentioned here will be picked up by converse.js's
......@@ -71,52 +71,8 @@ converse.plugins.add('converse-headline', {
});
_converse.HeadlinesBoxView = _converse.ChatBoxView.extend({
className: 'chatbox headlines',
events: {
'click .close-chatbox-button': 'close',
'click .toggle-chatbox-button': 'minimize',
'keypress textarea.chat-textarea': 'onKeyDown'
},
initialize () {
this.initDebounced();
this.model.disable_mam = true; // Don't do MAM queries for this box
this.listenTo(this.model.messages, 'add', this.onMessageAdded);
this.listenTo(this.model, 'show', this.show);
this.listenTo(this.model, 'destroy', this.hide);
this.listenTo(this.model, 'change:minimized', this.onMinimizedChanged);
this.render().insertHeading()
this.updateAfterMessagesFetched();
this.insertIntoDOM().hide();
_converse.api.trigger('chatBoxInitialized', this);
},
render () {
this.el.setAttribute('id', this.model.get('box_id'))
this.el.innerHTML = tpl_chatbox(
Object.assign(this.model.toJSON(), {
info_close: '',
label_personal_message: '',
show_send_button: false,
show_toolbar: false,
unread_msgs: ''
}
));
this.content = this.el.querySelector('.chat-content');
return this;
},
// Override to avoid the methods in converse-chatview.js
'renderMessageForm': function renderMessageForm () {},
'afterShown': function afterShown () {}
});
async function onHeadlineMessage (message) {
/* Handler method for all incoming messages of type "headline". */
// Handler method for all incoming messages of type "headline".
if (utils.isHeadlineMessage(_converse, message)) {
const from_jid = message.getAttribute('from');
if (from_jid.includes('@') &&
......@@ -140,6 +96,8 @@ converse.plugins.add('converse-headline', {
}
}
/************************ BEGIN Event Handlers ************************/
function registerHeadlineHandler () {
_converse.connection.addHandler(message => {
onHeadlineMessage(message);
......@@ -148,15 +106,52 @@ converse.plugins.add('converse-headline', {
}
_converse.api.listen.on('connected', registerHeadlineHandler);
_converse.api.listen.on('reconnected', registerHeadlineHandler);
_converse.api.listen.on('chatBoxViewsInitialized', () => {
const views = _converse.chatboxviews;
_converse.chatboxes.on('add', item => {
if (!views.get(item.get('id')) && item.get('type') === _converse.HEADLINES_TYPE) {
views.add(item.get('id'), new _converse.HeadlinesBoxView({model: item}));
/************************ END Event Handlers ************************/
/************************ BEGIN API ************************/
Object.assign(_converse.api, {
/**
* The "headlines" namespace, which is used for headline-channels
* which are read-only channels containing messages of type
* "headline".
*
* @namespace _converse.api.headlines
* @memberOf _converse.api
*/
headlines: {
/**
* Retrieves a headline-channel or all headline-channels.
*
* @method _converse.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 _converse.api.chatboxes.get(jid);
if (!model && create) {
model = await _converse.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 _converse.api.chatboxes.get();
return chats.filter(c => (c.get('type') === _converse.HEADLINES_TYPE));
} else if (isString(jids)) {
return _get(jids);
}
return Promise.all(jids.map(jid => _get(jid)));
}
});
}
});
/************************ END API ************************/
}
});
......@@ -117,7 +117,7 @@ converse.plugins.add('converse-mam', {
}
const message_handler = is_groupchat ?
this.onMessage.bind(this) :
_converse.chatboxes.onMessage.bind(_converse.chatboxes);
_converse.handleMessageStanza.bind(_converse.chatboxes);
const query = Object.assign({
'groupchat': is_groupchat,
......
This diff is collapsed.
......@@ -6,15 +6,17 @@ import "./converse-bookmarks"; // XEP-0199 XMPP Ping
import "./converse-bosh"; // XEP-0206 BOSH
import "./converse-caps"; // XEP-0115 Entity Capabilities
import "./converse-chatboxes"; // Backbone Collection and Models for chat boxes
import "./converse-chat"; // Support for one-on-one chats
import "./converse-disco"; // XEP-0030 Service discovery
import "./converse-mam"; // XEP-0313 Message Archive Management
import "./converse-muc"; // XEP-0045 Multi-user chat
import "./converse-headlines"; // Support for headline messages
import "./converse-ping"; // XEP-0199 XMPP Ping
import "./converse-pubsub"; // XEP-0060 Pubsub
import "./converse-roster"; // Contacts Roster
import "./converse-rsm"; // XEP-0059 Result Set management
import "./converse-smacks"; // XEP-0198 Stream Management
import "./converse-status"; // XEP-0199 XMPP Ping
import "./converse-status"; // XEP-0199 XMPP Ping
import "./converse-vcard"; // XEP-0054 VCard-temp
/* END: Removable components */
......
......@@ -52,7 +52,7 @@
};
utils.openControlBox = async function (_converse) {
const model = await _converse.api.chats.open('controlbox');
const model = await _converse.api.controlbox.open();
await u.waitUntil(() => model.get('connected'));
var toggle = document.querySelector(".toggle-controlbox");
if (!u.isVisible(document.querySelector("#controlbox"))) {
......@@ -121,7 +121,7 @@
utils.openChatRoomViaModal = async function (_converse, jid, nick='') {
// Opens a new chatroom
const model = await _converse.api.chats.open('controlbox');
const model = await _converse.api.controlbox.open('controlbox');
await u.waitUntil(() => model.get('connected'));
utils.openControlBox();
const view = await _converse.chatboxviews.get('controlbox');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment