Commit ce30b64b authored by JC Brand's avatar JC Brand Committed by GitHub

Merge branch 'master' into 1257_notifications-prefer-probably-over-maybe

parents daa1654d 6904f9a8
{
"parserOptions": {
"ecmaVersion": 2017
"ecmaVersion": 2017,
"sourceType": "module"
},
"env": {
"browser": true,
......
# Changelog
## 4.1.0 (Unreleased)
- Use [Lerna](https://lernajs.io/) to create the @converse/headless package
- Use ES2015 modules instead of UMD.
- #1257: Prefer 'probably' over 'maybe' when evaluating audio play support.
## 4.0.3 (2018-10-22)
......
......@@ -157,12 +157,16 @@ watchcss: dev
$(SASS) --watch -I $(BOURBON) -I $(BOOTSTRAP) sass:css
.PHONY: watchjs
watchjs: dev
watchjs: dev dist/converse-headless.js
./node_modules/.bin/npx webpack --mode=development --watch
.PHONY: watchjsheadless
watchjsheadless: dev
./node_modules/.bin/npx webpack --mode=development --watch --type=headless
.PHONY: watch
watch: dev
make -j 2 watchjs watchcss
make -j 3 watchcss watchjsheadless watchjs
.PHONY: logo
logo: logo/conversejs-transparent16.png \
......
This diff is collapsed.
......@@ -1555,34 +1555,32 @@
it("properly handles notification that a room has been destroyed",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
async function (done, _converse) {
test_utils.openChatRoomViaModal(_converse, 'problematic@muc.localhost', 'dummy')
.then(function () {
const presence = $pres().attrs({
from:'problematic@muc.localhost',
id:'n13mt3l',
to:'dummy@localhost/pda',
type:'error'})
.c('error').attrs({'type':'cancel'})
.c('gone').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'})
.t('xmpp:other-room@chat.jabberfr.org?join').up()
.c('text').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'})
.t("We didn't like the name").nodeTree;
const view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.el.querySelector('.chatroom-body .disconnect-msg').textContent)
.toBe('This room no longer exists');
expect(view.el.querySelector('.chatroom-body .destroyed-reason').textContent)
.toBe(`"We didn't like the name"`);
expect(view.el.querySelector('.chatroom-body .moved-label').textContent.trim())
.toBe('The conversation has moved. Click below to enter.');
expect(view.el.querySelector('.chatroom-body .moved-link').textContent.trim())
.toBe(`other-room@chat.jabberfr.org`);
done();
}).catch(_.partial(console.error, _));
await test_utils.openChatRoomViaModal(_converse, 'problematic@muc.localhost', 'dummy')
const presence = $pres().attrs({
from:'problematic@muc.localhost',
id:'n13mt3l',
to:'dummy@localhost/pda',
type:'error'})
.c('error').attrs({'type':'cancel'})
.c('gone').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'})
.t('xmpp:other-room@chat.jabberfr.org?join').up()
.c('text').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'})
.t("We didn't like the name").nodeTree;
const view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.el.querySelector('.chatroom-body .disconnect-msg').textContent)
.toBe('This room no longer exists');
expect(view.el.querySelector('.chatroom-body .destroyed-reason').textContent)
.toBe(`"We didn't like the name"`);
expect(view.el.querySelector('.chatroom-body .moved-label').textContent.trim())
.toBe('The conversation has moved. Click below to enter.');
expect(view.el.querySelector('.chatroom-body .moved-link').textContent.trim())
.toBe(`other-room@chat.jabberfr.org`);
done();
}));
it("will use the user's reserved nickname, if it exists",
......
......@@ -12,46 +12,41 @@
describe("A list of open rooms", function () {
it("is shown in the \"Rooms\" panel", mock.initConverseWithPromises(
null, ['rosterGroupsFetched', 'chatBoxesFetched'],
{ allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic.
},
function (done, _converse) {
test_utils.openControlBox();
const controlbox = _converse.chatboxviews.get('controlbox');
let list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
null, ['rosterGroupsFetched', 'chatBoxesFetched'],
{ allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic.
}, async function (done, _converse) {
let room_els;
test_utils.openControlBox();
const controlbox = _converse.chatboxviews.get('controlbox');
let list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC')
.then(() => {
expect(_.isUndefined(_converse.rooms_list_view)).toBeFalsy();
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('room@conference.shakespeare.lit');
return test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
}).then(() => {
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2);
await test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC');
expect(_.isUndefined(_converse.rooms_list_view)).toBeFalsy();
let room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('room@conference.shakespeare.lit');
await test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2);
var view = _converse.chatboxviews.get('room@conference.shakespeare.lit');
view.close();
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('lounge@localhost');
list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeFalsy();
let view = _converse.chatboxviews.get('room@conference.shakespeare.lit');
view.close();
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('lounge@localhost');
list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeFalsy();
view = _converse.chatboxviews.get('lounge@localhost');
view.close();
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(0);
view = _converse.chatboxviews.get('lounge@localhost');
view.close();
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(0);
list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
list = controlbox.el.querySelector('div.rooms-list-container');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
done();
}
));
});
......
This diff is collapsed.
This diff is collapsed.
......@@ -4,60 +4,58 @@
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) {
define(["@converse/headless/converse-core"], factory);
}(this, function (converse) {
const { Strophe, $build, _, b64_sha1 } = converse.env;
import converse from "@converse/headless/converse-core";
Strophe.addNamespace('CAPS', "http://jabber.org/protocol/caps");
const { Strophe, $build, _, b64_sha1 } = converse.env;
function propertySort (array, property) {
return array.sort((a, b) => { return a[property] > b[property] ? -1 : 1 });
}
function generateVerificationString (_converse) {
const identities = _converse.api.disco.own.identities.get(),
features = _converse.api.disco.own.features.get();
if (identities.length > 1) {
propertySort(identities, "category");
propertySort(identities, "type");
propertySort(identities, "lang");
}
Strophe.addNamespace('CAPS', "http://jabber.org/protocol/caps");
let S = _.reduce(
identities,
(result, id) => `${result}${id.category}/${id.type}/${_.get(id, 'lang', '')}/${id.name}<`,
"");
function propertySort (array, property) {
return array.sort((a, b) => { return a[property] > b[property] ? -1 : 1 });
}
features.sort();
S = _.reduce(features, (result, feature) => `${result}${feature}<`, S);
return b64_sha1(S);
}
function generateVerificationString (_converse) {
const identities = _converse.api.disco.own.identities.get(),
features = _converse.api.disco.own.features.get();
function createCapsNode (_converse) {
return $build("c", {
'xmlns': Strophe.NS.CAPS,
'hash': "sha-1",
'node': "https://conversejs.org",
'ver': generateVerificationString(_converse)
}).nodeTree;
if (identities.length > 1) {
propertySort(identities, "category");
propertySort(identities, "type");
propertySort(identities, "lang");
}
converse.plugins.add('converse-caps', {
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.
XMPPStatus: {
constructPresence () {
const presence = this.__super__.constructPresence.apply(this, arguments);
presence.root().cnode(createCapsNode(this.__super__._converse));
return presence;
}
let S = _.reduce(
identities,
(result, id) => `${result}${id.category}/${id.type}/${_.get(id, 'lang', '')}/${id.name}<`,
"");
features.sort();
S = _.reduce(features, (result, feature) => `${result}${feature}<`, S);
return b64_sha1(S);
}
function createCapsNode (_converse) {
return $build("c", {
'xmlns': Strophe.NS.CAPS,
'hash': "sha-1",
'node': "https://conversejs.org",
'ver': generateVerificationString(_converse)
}).nodeTree;
}
converse.plugins.add('converse-caps', {
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.
XMPPStatus: {
constructPresence () {
const presence = this.__super__.constructPresence.apply(this, arguments);
presence.root().cnode(createCapsNode(this.__super__._converse));
return presence;
}
}
});
}));
}
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Converse.js
// http://conversejs.org
//
// Copyright (c) 2012-2018, the Converse.js developers
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) {
define(["@converse/headless/converse-core", "@converse/headless/converse-muc"], factory);
}(this, function (converse) {
"use strict";
const { Backbone, _ } = converse.env;
import "@converse/headless/converse-muc";
import converse from "@converse/headless/converse-core";
converse.plugins.add('converse-embedded', {
const { Backbone, _ } = converse.env;
enabled (_converse) {
return _converse.view_mode === 'embedded';
},
converse.plugins.add('converse-embedded', {
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
this._converse.api.settings.update({
'allow_logout': false, // No point in logging out when we have auto_login as true.
'allow_muc_invitations': false, // Doesn't make sense to allow because only
// roster contacts can be invited
'hide_muc_server': true
});
const { _converse } = this;
if (!_.isArray(_converse.auto_join_rooms) && !_.isArray(_converse.auto_join_private_chats)) {
throw new Error("converse-embedded: auto_join_rooms must be an Array");
}
if (_converse.auto_join_rooms.length > 1 && _converse.auto_join_private_chats.length > 1) {
throw new Error("converse-embedded: It doesn't make "+
"sense to have the auto_join_rooms setting more then one, "+
"since only one chat room can be open at any time.");
}
enabled (_converse) {
return _converse.view_mode === 'embedded';
},
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
this._converse.api.settings.update({
'allow_logout': false, // No point in logging out when we have auto_login as true.
'allow_muc_invitations': false, // Doesn't make sense to allow because only
// roster contacts can be invited
'hide_muc_server': true
});
const { _converse } = this;
if (!_.isArray(_converse.auto_join_rooms) && !_.isArray(_converse.auto_join_private_chats)) {
throw new Error("converse-embedded: auto_join_rooms must be an Array");
}
if (_converse.auto_join_rooms.length > 1 && _converse.auto_join_private_chats.length > 1) {
throw new Error("converse-embedded: It doesn't make "+
"sense to have the auto_join_rooms setting more then one, "+
"since only one chat room can be open at any time.");
}
});
}));
}
});
......@@ -4,57 +4,52 @@
// Copyright (c) JC Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
//
/*global define */
(function (root, factory) {
define(["@converse/headless/converse-core",
"templates/inverse_brand_heading.html",
"converse-chatview",
"converse-controlbox",
"@converse/headless/converse-muc",
"converse-singleton"
], factory);
}(this, function (converse, tpl_brand_heading) {
"use strict";
const { Strophe, _ } = converse.env;
converse.plugins.add('converse-fullscreen', {
enabled (_converse) {
return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
},
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.
ControlBoxView: {
createBrandHeadingHTML() {
return tpl_brand_heading();
},
insertBrandHeading () {
const { _converse } = this.__super__;
const el = _converse.root.getElementById('converse-login-panel');
el.parentNode.insertAdjacentHTML(
'afterbegin',
this.createBrandHeadingHTML()
);
}
import "@converse/headless/converse-muc";
import "converse-chatview";
import "converse-controlbox";
import "converse-singleton";
import converse from "@converse/headless/converse-core";
import tpl_brand_heading from "templates/inverse_brand_heading.html";
const { Strophe, _ } = converse.env;
converse.plugins.add('converse-fullscreen', {
enabled (_converse) {
return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
},
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.
ControlBoxView: {
createBrandHeadingHTML() {
return tpl_brand_heading();
},
insertBrandHeading () {
const { _converse } = this.__super__;
const el = _converse.root.getElementById('converse-login-panel');
el.parentNode.insertAdjacentHTML(
'afterbegin',
this.createBrandHeadingHTML()
);
}
},
initialize () {
this._converse.api.settings.update({
chatview_avatar_height: 50,
chatview_avatar_width: 50,
hide_open_bookmarks: true,
show_controlbox_by_default: true,
sticky_controlbox: true
});
}
});
}));
},
initialize () {
this._converse.api.settings.update({
chatview_avatar_height: 50,
chatview_avatar_width: 50,
hide_open_bookmarks: true,
show_controlbox_by_default: true,
sticky_controlbox: true
});
}
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Converse.js
// http://conversejs.org
//
// Copyright (c) 2018, the Converse.js developers
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([
"@converse/headless/converse-core",
"templates/alert_modal.html",
"bootstrap",
"backbone.vdomview"
], factory);
}
}(this, function (converse, tpl_alert_modal, bootstrap) {
"use strict";
const { Strophe, Backbone, _ } = converse.env;
converse.plugins.add('converse-modal', {
initialize () {
const { _converse } = this;
_converse.BootstrapModal = Backbone.VDOMView.extend({
initialize () {
this.render().insertIntoDOM();
this.modal = new bootstrap.Modal(this.el, {
backdrop: 'static',
keyboard: true
});
this.el.addEventListener('hide.bs.modal', (event) => {
if (!_.isNil(this.trigger_el)) {
this.trigger_el.classList.remove('selected');
}
}, false);
},
insertIntoDOM () {
const container_el = _converse.chatboxviews.el.querySelector("#converse-modals");
container_el.insertAdjacentElement('beforeEnd', this.el);
},
show (ev) {
if (ev) {
ev.preventDefault();
this.trigger_el = ev.target;
this.trigger_el.classList.add('selected');
}
this.modal.show();
}
});
import "backbone.vdomview";
import bootstrap from "bootstrap";
import converse from "@converse/headless/converse-core";
import tpl_alert_modal from "templates/alert_modal.html";
_converse.Alert = _converse.BootstrapModal.extend({
const { Strophe, Backbone, _ } = converse.env;
initialize () {
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
this.model.on('change', this.render, this);
},
toHTML () {
return tpl_alert_modal(this.model.toJSON());
}
});
converse.plugins.add('converse-modal', {
_converse.api.listen.on('afterTearDown', () => {
if (!_converse.chatboxviews) {
return;
}
const container = _converse.chatboxviews.el.querySelector("#converse-modals");
if (container) {
container.innerHTML = '';
initialize () {
const { _converse } = this;
_converse.BootstrapModal = Backbone.VDOMView.extend({
initialize () {
this.render().insertIntoDOM();
this.modal = new bootstrap.Modal(this.el, {
backdrop: 'static',
keyboard: true
});
this.el.addEventListener('hide.bs.modal', (event) => {
if (!_.isNil(this.trigger_el)) {
this.trigger_el.classList.remove('selected');
}
}, false);
},
insertIntoDOM () {
const container_el = _converse.chatboxviews.el.querySelector("#converse-modals");
container_el.insertAdjacentElement('beforeEnd', this.el);
},
show (ev) {
if (ev) {
ev.preventDefault();
this.trigger_el = ev.target;
this.trigger_el.classList.add('selected');
}
});
/************************ BEGIN API ************************/
// We extend the default converse.js API to add methods specific to MUC chat rooms.
let alert
_.extend(_converse.api, {
'alert': {
'show' (type, title, messages) {
if (_.isString(messages)) {
messages = [messages];
}
if (type === Strophe.LogLevel.ERROR) {
type = 'alert-danger';
} else if (type === Strophe.LogLevel.INFO) {
type = 'alert-info';
} else if (type === Strophe.LogLevel.WARN) {
type = 'alert-warning';
}
if (_.isUndefined(alert)) {
const model = new Backbone.Model({
'title': title,
'messages': messages,
'type': type
})
alert = new _converse.Alert({'model': model});
} else {
alert.model.set({
'title': title,
'messages': messages,
'type': type
});
}
alert.show();
this.modal.show();
}
});
_converse.Alert = _converse.BootstrapModal.extend({
initialize () {
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
this.model.on('change', this.render, this);
},
toHTML () {
return tpl_alert_modal(this.model.toJSON());
}
});
_converse.api.listen.on('afterTearDown', () => {
if (!_converse.chatboxviews) {
return;
}
const container = _converse.chatboxviews.el.querySelector("#converse-modals");
if (container) {
container.innerHTML = '';
}
});
/************************ BEGIN API ************************/
// We extend the default converse.js API to add methods specific to MUC chat rooms.
let alert
_.extend(_converse.api, {
'alert': {
'show' (type, title, messages) {
if (_.isString(messages)) {
messages = [messages];
}
if (type === Strophe.LogLevel.ERROR) {
type = 'alert-danger';
} else if (type === Strophe.LogLevel.INFO) {
type = 'alert-info';
} else if (type === Strophe.LogLevel.WARN) {
type = 'alert-warning';
}
if (_.isUndefined(alert)) {
const model = new Backbone.Model({
'title': title,
'messages': messages,
'type': type
})
alert = new _converse.Alert({'model': model});
} else {
alert.model.set({
'title': title,
'messages': messages,
'type': type
});
}
alert.show();
}
});
}
});
}));
}
});
}
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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