Merge branch 'master' into converse-omemo

This commit is contained in:
JC Brand 2018-07-25 12:06:42 +02:00
commit f40e4b4dbb
4 changed files with 160 additions and 135 deletions

234
dist/converse.js vendored
View File

@ -86,108 +86,6 @@
/************************************************************************/
/******/ ({
/***/ "../backbone.vdomview/backbone.vdomview.js":
/*!*************************************************!*\
!*** ../backbone.vdomview/backbone.vdomview.js ***!
\*************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
/*!
* Backbone.VDOMView
*
* MIT Licensed. Copyright (c) 2017, JC Brand <jc@opkode.com>
*/
(function (root, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! snabbdom */ "./node_modules/snabbdom/dist/snabbdom.js"), __webpack_require__(/*! snabbdom-attributes */ "./node_modules/snabbdom/dist/snabbdom-attributes.js"), __webpack_require__(/*! snabbdom-class */ "./node_modules/snabbdom/dist/snabbdom-class.js"), __webpack_require__(/*! snabbdom-dataset */ "./node_modules/snabbdom/dist/snabbdom-dataset.js"), __webpack_require__(/*! snabbdom-props */ "./node_modules/snabbdom/dist/snabbdom-props.js"), __webpack_require__(/*! snabbdom-style */ "./node_modules/snabbdom/dist/snabbdom-style.js"), __webpack_require__(/*! tovnode */ "./node_modules/snabbdom/dist/tovnode.js"), __webpack_require__(/*! underscore */ "./src/underscore-shim.js"), __webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
})(void 0, function (snabbdom, snabbdom_attributes, snabbdom_class, snabbdom_dataset, snabbdom_props, snabbdom_style, tovnode, _, Backbone) {
"use strict";
let domParser = new DOMParser();
const patch = snabbdom.init([snabbdom_attributes.default, snabbdom_class.default, snabbdom_dataset.default, snabbdom_props.default, snabbdom_style.default]);
const View = _.isUndefined(Backbone.NativeView) ? Backbone.View : Backbone.NativeView;
function parseHTMLToDOM(html_str) {
/* Parses a string with HTML and returns a DOM element.
*
* Forked from vdom_parser:
* https://github.com/bitinn/vdom-parser
*/
if (typeof html_str !== 'string') {
throw new Error('Invalid parameter type in parseHTMLToDOM');
}
if (!('DOMParser' in window)) {
throw new Error('DOMParser is not available, ' + 'so parsing string to DOM node is not possible.');
}
if (!html_str) {
return document.createTextNode('');
}
domParser = domParser || new DOMParser();
const doc = domParser.parseFromString(html_str, 'text/html'); // most tags default to body
if (doc.body.firstChild) {
return doc.getElementsByTagName('body')[0].firstChild; // some tags, like script and style, default to head
} else if (doc.head.firstChild && (doc.head.firstChild.tagName !== 'TITLE' || doc.title)) {
return doc.head.firstChild; // special case for html comment, cdata, doctype
} else if (doc.firstChild && doc.firstChild.tagName !== 'HTML') {
return doc.firstChild; // other element, such as whitespace, or html/body/head tag, fallback to empty text node
} else {
return document.createTextNode('');
}
}
Backbone.VDOMView = View.extend({
updateEventListeners(old_vnode, new_vnode) {
this.setElement(new_vnode.elm);
},
render() {
if (_.isFunction(this.beforeRender)) {
this.beforeRender();
}
let new_vnode;
if (!_.isNil(this.toHTML)) {
new_vnode = tovnode.toVNode(parseHTMLToDOM(this.toHTML()));
} else {
new_vnode = tovnode.toVNode(this.toDOM());
}
new_vnode.data.hook = _.extend({
create: this.updateEventListeners.bind(this),
update: this.updateEventListeners.bind(this)
});
const el = this.vnode ? this.vnode.elm : this.el;
if (el.outerHTML !== new_vnode.elm.outerHTML) {
this.vnode = patch(this.vnode || this.el, new_vnode);
}
if (_.isFunction(this.afterRender)) {
this.afterRender();
}
return this;
}
});
return Backbone.VDOMView;
});
/***/ }),
/***/ "./3rdparty/lodash.fp.js":
/*!*******************************!*\
!*** ./3rdparty/lodash.fp.js ***!
@ -2571,6 +2469,132 @@ backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_mod
/***/ }),
/***/ "./node_modules/backbone.vdomview/backbone.vdomview.js":
/*!*************************************************************!*\
!*** ./node_modules/backbone.vdomview/backbone.vdomview.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
var backbone = (backbone || {});
backbone.nativeview = __webpack_require__(/*! backbone.nativeview */ "./node_modules/backbone.nativeview/backbone.nativeview.js");
/*!
* Backbone.VDOMView
*
* MIT Licensed. Copyright (c) 2017, JC Brand <jc@opkode.com>
*/
(function (root, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
__webpack_require__(/*! snabbdom */ "./node_modules/snabbdom/dist/snabbdom.js"),
__webpack_require__(/*! snabbdom-attributes */ "./node_modules/snabbdom/dist/snabbdom-attributes.js"),
__webpack_require__(/*! snabbdom-class */ "./node_modules/snabbdom/dist/snabbdom-class.js"),
__webpack_require__(/*! snabbdom-dataset */ "./node_modules/snabbdom/dist/snabbdom-dataset.js"),
__webpack_require__(/*! snabbdom-props */ "./node_modules/snabbdom/dist/snabbdom-props.js"),
__webpack_require__(/*! snabbdom-style */ "./node_modules/snabbdom/dist/snabbdom-style.js"),
__webpack_require__(/*! tovnode */ "./node_modules/snabbdom/dist/tovnode.js"),
__webpack_require__(/*! underscore */ "./src/underscore-shim.js"),
__webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js")
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(this, function (
snabbdom,
snabbdom_attributes,
snabbdom_class,
snabbdom_dataset,
snabbdom_props,
snabbdom_style,
tovnode,
_,
Backbone) {
"use strict";
let domParser = new DOMParser();
const patch = snabbdom.init([
snabbdom_attributes.default,
snabbdom_class.default,
snabbdom_dataset.default,
snabbdom_props.default,
snabbdom_style.default
]);
const View = _.isUndefined(Backbone.NativeView) ? Backbone.View : Backbone.NativeView;
function parseHTMLToDOM (html_str) {
/* Parses a string with HTML and returns a DOM element.
*
* Forked from vdom_parser:
* https://github.com/bitinn/vdom-parser
*/
if (typeof html_str !== 'string') {
throw new Error('Invalid parameter type in parseHTMLToDOM');
}
if ( !('DOMParser' in window) ) {
throw new Error(
'DOMParser is not available, '+
'so parsing string to DOM node is not possible.');
}
if (!html_str) {
return document.createTextNode('');
}
domParser = domParser || new DOMParser();
const doc = domParser.parseFromString(html_str, 'text/html');
// most tags default to body
if (doc.body.firstChild) {
return doc.getElementsByTagName('body')[0].firstChild;
// some tags, like script and style, default to head
} else if (doc.head.firstChild && (doc.head.firstChild.tagName !== 'TITLE' || doc.title)) {
return doc.head.firstChild;
// special case for html comment, cdata, doctype
} else if (doc.firstChild && doc.firstChild.tagName !== 'HTML') {
return doc.firstChild;
// other element, such as whitespace, or html/body/head tag, fallback to empty text node
} else {
return document.createTextNode('');
}
}
Backbone.VDOMView = View.extend({
updateEventListeners (old_vnode, new_vnode) {
this.setElement(new_vnode.elm);
},
render () {
if (_.isFunction(this.beforeRender)) {
this.beforeRender();
}
const new_vnode = tovnode.toVNode(parseHTMLToDOM(this.toHTML()));
new_vnode.data.hook = _.extend({
create: this.updateEventListeners.bind(this),
update: this.updateEventListeners.bind(this)
});
const el = this.vnode ? this.vnode.elm : this.el;
if (el.outerHTML !== new_vnode.elm.outerHTML) {
this.vnode = patch(this.vnode || this.el, new_vnode);
}
if (_.isFunction(this.afterRender)) {
this.afterRender();
}
return this;
}
});
return Backbone.VDOMView;
}));
/***/ }),
/***/ "./node_modules/backbone/backbone.js":
@ -69263,7 +69287,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! templates/alert_modal.html */ "./src/templates/alert_modal.html"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! backbone.vdomview */ "../backbone.vdomview/backbone.vdomview.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! templates/alert_modal.html */ "./src/templates/alert_modal.html"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! backbone.vdomview */ "./node_modules/backbone.vdomview/backbone.vdomview.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
@ -69733,7 +69757,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// For translators: %1$s is a variable and will be
// replaced with the XMPP server name
available_chatrooms.innerHTML = tpl_rooms_results({
'feedback_text': __('groupchats found:')
'feedback_text': __('Groupchats found:')
});
const fragment = document.createDocumentFragment();
@ -71355,7 +71379,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! utils/form */ "./src/utils/form.js"), __webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! converse-disco */ "./src/converse-disco.js"), __webpack_require__(/*! backbone.overview */ "./node_modules/backbone.overview/backbone.overview.js"), __webpack_require__(/*! backbone.orderedlistview */ "./node_modules/backbone.overview/backbone.orderedlistview.js"), __webpack_require__(/*! backbone.vdomview */ "../backbone.vdomview/backbone.vdomview.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! utils/form */ "./src/utils/form.js"), __webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! converse-disco */ "./src/converse-disco.js"), __webpack_require__(/*! backbone.overview */ "./node_modules/backbone.overview/backbone.overview.js"), __webpack_require__(/*! backbone.orderedlistview */ "./node_modules/backbone.overview/backbone.orderedlistview.js"), __webpack_require__(/*! backbone.vdomview */ "./node_modules/backbone.vdomview/backbone.vdomview.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

View File

@ -54,7 +54,7 @@
}).catch(_.partial(console.error, _));
}));
it("has a method 'get' which returns a wrapped chat room (if it exists)",
it("has a method 'get' which returns a wrapped groupchat (if it exists)",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -126,7 +126,7 @@
}, 300).then(function () {
var jid = 'lounge@localhost';
var room = _converse.api.rooms.open(jid);
// Test on chat room that's not yet open
// Test on groupchat that's not yet open
expect(room instanceof Object).toBeTruthy();
var chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.is_chatroom).toBeTruthy();
@ -275,7 +275,7 @@
}));
});
describe("An instant chat room", function () {
describe("An instant groupchat", function () {
it("will be created when muc_instant_rooms is set to true",
mock.initConverseWithPromises(
@ -407,9 +407,9 @@
}));
});
describe("A Chat Room", function () {
describe("A Groupchat", function () {
it("shows join/leave messages when users enter or exit a room",
it("shows join/leave messages when users enter or exit a groupchat",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -664,7 +664,7 @@
jasmine.clock().tick(ONE_DAY_LATER);
// Test a user leaving a chat room
// Test a user leaving a groupchat
presence = $pres({
to: 'dummy@localhost/_converse.js-29092160',
type: 'unavailable',
@ -738,7 +738,7 @@
jasmine.clock().tick(ONE_DAY_LATER);
// Test a user leaving a chat room
// Test a user leaving a groupchat
presence = $pres({
to: 'dummy@localhost/_converse.js-29092160',
type: 'unavailable',
@ -1419,7 +1419,7 @@
});
}));
it("allows the user to invite their roster contacts to enter the chat room",
it("allows the user to invite their roster contacts to enter the groupchat",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -1497,7 +1497,7 @@
var name = mock.cur_names[0];
var from_jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var room_jid = 'lounge@localhost';
var reason = "Please join this chat room";
var reason = "Please join this groupchat";
expect(_converse.chatboxes.models.length).toBe(1);
expect(_converse.chatboxes.models[0].id).toBe("controlbox");
@ -1508,7 +1508,7 @@
'</message>').firstChild;
_converse.onDirectMUCInvitation(stanza);
expect(window.confirm).toHaveBeenCalledWith(
name + ' has invited you to join a chat room: '+ room_jid +
name + ' has invited you to join a groupchat: '+ room_jid +
', and left the following reason: "'+reason+'"');
expect(_converse.chatboxes.models.length).toBe(2);
expect(_converse.chatboxes.models[0].id).toBe('controlbox');
@ -1959,7 +1959,7 @@
});
}));
it("informs users if they have been kicked out of the chat room",
it("informs users if they have been kicked out of the groupchat",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -2871,7 +2871,7 @@
spyOn(view, 'showErrorMessage').and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
.toBe('You are not allowed to create new rooms.');
.toBe('You are not allowed to create new groupchats.');
done();
}).catch(_.partial(console.error, _));
}));
@ -2949,9 +2949,9 @@
}));
});
describe("Someone being invited to a chat room", function () {
describe("Someone being invited to a groupchat", function () {
it("will first be added to the member list if the chat room is members only",
it("will first be added to the member list if the groupchat is members only",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -3002,7 +3002,7 @@
});
var name = mock.cur_names[0];
invitee_jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var reason = "Please join this chat room";
var reason = "Please join this groupchat";
view.model.directInvite(invitee_jid, reason);
// Check in reverse order that we requested all three lists
@ -3088,7 +3088,7 @@
var iq = "<iq to='coven@chat.shakespeare.lit' type='set' xmlns='jabber:client' id='"+IQ_ids.pop()+"'>"+
"<query xmlns='http://jabber.org/protocol/muc#admin'>"+
"<item affiliation='member' jid='"+invitee_jid+"'>"+
"<reason>Please join this chat room</reason>"+
"<reason>Please join this groupchat</reason>"+
"</item>"+
"</query>"+
"</iq>";
@ -3097,8 +3097,9 @@
// Finally check that the user gets invited.
expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec)
"<message from='dummy@localhost/resource' to='"+invitee_jid+"' id='"+sent_id+"' xmlns='jabber:client'>"+
"<x xmlns='jabber:x:conference' jid='coven@chat.shakespeare.lit' reason='Please join this chat room'/>"+
"</message>");
"<x xmlns='jabber:x:conference' jid='coven@chat.shakespeare.lit' reason='Please join this groupchat'/>"+
"</message>"
);
done();
});
}));
@ -3169,7 +3170,7 @@
}));
});
describe("The \"Chatrooms\" section", function () {
describe("The \"Groupchats\" section", function () {
it("contains a link to a modal through which a new chatroom can be created",
mock.initConverseWithPromises(
@ -3197,7 +3198,7 @@
}).catch(_.partial(console.error, _));
}));
it("contains a link to a modal which can list rooms publically available on the server",
it("contains a link to a modal which can list groupchats publically available on the server",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
@ -3252,7 +3253,7 @@
expect(modal.el.querySelectorAll('.available-chatrooms li').length).toBe(5);
const rooms = modal.el.querySelectorAll('.available-chatrooms li');
expect(rooms[0].textContent.trim()).toBe("Rooms found:");
expect(rooms[0].textContent.trim()).toBe("Groupchats found:");
expect(rooms[1].textContent.trim()).toBe("A Lonely Heath");
expect(rooms[2].textContent.trim()).toBe("A Dark Cave");
expect(rooms[3].textContent.trim()).toBe("The Palace");

View File

@ -154,17 +154,17 @@
const modal = view.model.room_details_modal;
let els = modal.el.querySelectorAll('p.room-info');
expect(els[0].textContent).toBe("Name: A Dark Cave")
expect(els[1].textContent).toBe("Room address (JID): coven@chat.shakespeare.lit")
expect(els[1].textContent).toBe("Groupchat address (JID): coven@chat.shakespeare.lit")
expect(els[2].textContent).toBe("Description: This is the description")
expect(els[3].textContent).toBe("Online users: 1")
const features_list = modal.el.querySelector('.features-list');
expect(features_list.textContent.replace(/(\n|\s{2,})/g, '')).toBe(
'Password protected - This room requires a password before entry'+
'Hidden - This room is not publicly searchable'+
'Open - Anyone can join this room'+
'Temporary - This room will disappear once the last person leaves'+
'Not anonymous - All other room occupants can see your XMPP username'+
'Not moderated - This room is not being moderated'
'Password protected - This groupchat requires a password before entry'+
'Hidden - This groupchat is not publicly searchable'+
'Open - Anyone can join this groupchat'+
'Temporary - This groupchat will disappear once the last person leaves'+
'Not anonymous - All other groupchat participants can see your XMPP username'+
'Not moderated - This groupchat is not being moderated'
);
const presence = $pres({
to: 'dummy@localhost/_converse.js-29092160',
@ -184,7 +184,7 @@
view.model.set({'subject': {'author': 'someone', 'text': 'Hatching dark plots'}});
els = modal.el.querySelectorAll('p.room-info');
expect(els[0].textContent).toBe("Name: A Dark Cave")
expect(els[1].textContent).toBe("Room address (JID): coven@chat.shakespeare.lit")
expect(els[1].textContent).toBe("Groupchat address (JID): coven@chat.shakespeare.lit")
expect(els[2].textContent).toBe("Description: This is the description")
expect(els[3].textContent).toBe("Topic: Hatching dark plots")
expect(els[4].textContent).toBe("Topic author: someone")

View File

@ -396,7 +396,7 @@
// For translators: %1$s is a variable and will be
// replaced with the XMPP server name
available_chatrooms.innerHTML = tpl_rooms_results({
'feedback_text': __('groupchats found:')
'feedback_text': __('Groupchats found:')
});
const fragment = document.createDocumentFragment();
const children = _.reject(_.map(this.rooms, this.roomStanzaItemToHTMLElement), _.isNil)