Commit 2de794ab authored by JC Brand's avatar JC Brand Committed by GitHub

Merge branch 'master' into master

parents 86730b86 a15aec35
......@@ -2,7 +2,7 @@
Contribution Guidelines
=======================
Thanks for contributing to `Converse.js <http://conversejs.org>`_.
Thanks for contributing to `Converse.js <https://conversejs.org>`_.
Support questions
=================
......
......@@ -2,8 +2,10 @@
## 4.1.3 (Unreleased)
- Updated translation: lt
- Upgrade to Backbone 1.4.0
- Fix "flashing" of roster filter when you have less than 5 roster contacts.
- Fix handling of CAPTCHAs offered by ejabberd.
- Allow setting of debug mode via URL with `/#converse?debug=true`
- New config setting [locked_muc_domain](https://conversejs.org/docs/html/configuration.html#locked-muc-domain)
- New config setting [show_client_info](https://conversejs.org/docs/html/configuration.html#show-client-info)
......@@ -13,7 +15,8 @@
- #1400: When a chat message is just an emoji, enlarge the emoji
- #1437: List of groupchats in modal doesn't scroll
- #1457: Wrong tooltip shown for "unbookmark" icon
- #1474: Update Lithuanian (lt) translation
- #1479: Allow file upload by drag & drop also in MUCs
## 4.1.2 (2019-02-22)
......@@ -647,7 +650,7 @@ More info here: https://github.com/LeaVerou/awesomplete/pull/17082
## 2.0.4 (2016-12-13)
- #737: Bugfix. Translations weren't being applied. [jcbrand]
- Fetch room info and store it on the room model.
For context, see: http://xmpp.org/extensions/xep-0045.html#disco-roominfo [jcbrand]
For context, see: https://xmpp.org/extensions/xep-0045.html#disco-roominfo [jcbrand]
- Bugfix. Switching from bookmarks form to config form shows only the spinner. [jcbrand]
- Bugfix. Other room occupants sometimes not shown when reloading the page. [jcbrand]
- Bugfix. Due to changes in `converse-core` the controlbox wasn't aware anymore of
......
......@@ -8,7 +8,7 @@
6. `git commit -am "New release 5.0.0"`
7. `git tag -s v5.0.0
8. Run `git push && git push --tags`
9. Update http://conversejs.org
9. Update https://conversejs.org
10. Create `5.0.0` directory for the CDN.
* Create a new version for the CDN by copying
* Check out the correct tag
......
......@@ -4,7 +4,7 @@
"type": "library",
"license": "MPL-2.0",
"minimum-stability": "stable",
"homepage": "http://conversejs.org/",
"homepage": "https://conversejs.org/",
"keywords": ["xmpp", "messaging", "chat", "presence"],
"require": {}
}
/*!
* Converse.js (Web-based XMPP instant messaging client)
* http://conversejs.org
* https://conversejs.org
*
* Copyright (c) 2013-2018, JC Brand <jc@opkode.com>
* Licensed under the Mozilla Public License
......
This diff is collapsed.
......@@ -222,7 +222,7 @@ allow_registration
* Default: ``true``
Support for `XEP-0077: In band registration <http://xmpp.org/extensions/xep-0077.html>`_
Support for `XEP-0077: In band registration <https://xmpp.org/extensions/xep-0077.html>`_
Allow XMPP account registration showing the corresponding UI register form interface.
......@@ -572,7 +572,7 @@ csi_waiting_time
* Default: ``0``
This option adds support for `XEP-0352 Client State Indication <http://xmpp.org/extensions/xep-0352.html>_`
This option adds support for `XEP-0352 Client State Indication <https://xmpp.org/extensions/xep-0352.html>_`
If Converse is idle for the configured amount of seconds, a chat state
indication of ``inactive`` will be sent out to the XMPP server (if the server
......@@ -806,7 +806,7 @@ See also:
Currently the "keepalive" setting only works with BOSH and not with
websockets. This is because XMPP over websocket does not use the same
session token as with BOSH. A possible solution for this is to implement
`XEP-0198 <http://xmpp.org/extensions/xep-0198.html>`_, specifically
`XEP-0198 <https://xmpp.org/extensions/xep-0198.html>`_, specifically
with regards to "stream resumption".
.. _`locales`:
......@@ -993,7 +993,7 @@ muc_instant_rooms
Determines whether 'instant' (also called 'dynamic' in OpenFire) rooms are created.
Otherwise rooms first have to be configured before they're available to other
users (so-called "registered rooms" in `MUC-0045 <http://xmpp.org/extensions/xep-0045.html#createroom>`_).
users (so-called "registered rooms" in `MUC-0045 <https://xmpp.org/extensions/xep-0045.html#createroom>`_).
From a UX perspective, if this settings is `false`, then a configuration form will
render, that has to be filled in first, before the room can be joined by other
......
......@@ -1050,7 +1050,7 @@ Room attributes that may be passed in:
configured automatically. Currently it doesn't make sense to specify
``roomconfig`` values if ``auto_configure`` is set to ``false``.
For a list of configuration values that can be passed in, refer to these values
in the `XEP-0045 MUC specification <http://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner>`_.
in the `XEP-0045 MUC specification <https://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner>`_.
The values should be named without the ``muc#roomconfig_`` prefix.
* *maximize*: A boolean, indicating whether minimized rooms should also be
maximized, when opened. Set to ``false`` by default.
......
......@@ -20,7 +20,7 @@ contribute, please read the :doc:`documentation` page.
Introduction
============
Converse is a free and open-source `XMPP <http://xmpp.org/about-xmpp/>`_
Converse is a free and open-source `XMPP <https://xmpp.org/about-xmpp/>`_
chat client written in JavaScript which can be tightly integrated into any website.
The benefit of using converse.js as opposed to relying on a SaaS
......
......@@ -57,7 +57,7 @@ The various components
An XMPP server
==============
Converse uses `XMPP <http://xmpp.org/about-xmpp/>`_ as its
Converse uses `XMPP <https://xmpp.org/about-xmpp/>`_ as its
messaging protocol, and therefore needs to connect to an XMPP/Jabber
server (Jabber® is an older and more user-friendly synonym for XMPP).
......@@ -67,7 +67,7 @@ authentication sessions to log in users to the XMPP server (i.e. :ref:`session s
then you'll have to set up your own XMPP server.
You can find a list of public XMPP servers/providers on `compliance.conversations.im <http://compliance.conversations.im/>`_
and a list of servers that you can set up yourself on `xmpp.org <http://xmpp.org/xmpp-software/servers/>`_.
and a list of servers that you can set up yourself on `xmpp.org <https://xmpp.org/xmpp-software/servers/>`_.
.. _`BOSH-section`:
......@@ -90,7 +90,7 @@ server, we need a proxy which acts as a bridge between these two protocols.
This is the job of a BOSH connection manager. BOSH (Bidirectional-streams Over
Synchronous HTTP) is a protocol for allowing XMPP communication over HTTP. The
protocol is defined in `XEP-0206: XMPP Over BOSH <http://xmpp.org/extensions/xep-0206.html>`_.
protocol is defined in `XEP-0206: XMPP Over BOSH <https://xmpp.org/extensions/xep-0206.html>`_.
Popular XMPP servers such as `Ejabberd <http://www.ejabberd.im>`_,
Prosody `(mod_bosh) <http://prosody.im/doc/setting_up_bosh>`_ and
......@@ -104,7 +104,7 @@ https://conversejs.org does), then you'll need a standalone connection manager.
For a standalone manager, see for example `Punjab <https://github.com/twonds/punjab>`_
and `node-xmpp-bosh <https://github.com/dhruvbird/node-xmpp-bosh>`_.
The demo on the `Converse homepage <http://conversejs.org>`_ uses a connection
The demo on the `Converse homepage <https://conversejs.org>`_ uses a connection
manager located at https://conversejs.org/http-bind.
This connection manager is available for testing purposes only, please don't
......@@ -258,7 +258,7 @@ Option 1). Server-side authentication via BOSH prebinding
---------------------------------------------------------
To **prebind** refers to a technique whereby your web application sets up an
authenticated BOSH session with the XMPP server or a standalone `BOSH <http://xmpp.org/about-xmpp/technology-overview/bosh/>`_
authenticated BOSH session with the XMPP server or a standalone `BOSH <https://xmpp.org/about-xmpp/technology-overview/bosh/>`_
connection manager.
Once authenticated, it receives RID and SID tokens which need to be passed
......
......@@ -11,7 +11,7 @@
<body>
<div id="header_wrap" class="outer">
<header class="inner">
<h1 id="project_title"><a href="http://conversejs.org">Converse.js</a></h1>
<h1 id="project_title"><a href="https://conversejs.org">Converse.js</a></h1>
<h2 id="project_tagline">Mockups</h2>
</header>
</div>
......
/*!
* Converse.js (Web-based XMPP instant messaging client)
* http://conversejs.org
* https://conversejs.org
*
* Copyright (c) 2013-2018, JC Brand <jc@opkode.com>
* Licensed under the Mozilla Public License
......
......@@ -18,45 +18,44 @@
it("shows all autocompletion options when the user presses @",
mock.initConverse(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom')
.then(() => {
const view = _converse.chatboxviews.get('lounge@localhost');
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(test_utils.createRequest(
$pres({
'to': 'tom@localhost/resource',
'from': `lounge@localhost/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@localhost/resource`,
'role': 'participant'
})));
});
async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom');
const view = _converse.chatboxviews.get('lounge@localhost');
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(test_utils.createRequest(
$pres({
'to': 'tom@localhost/resource',
'from': `lounge@localhost/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@localhost/resource`,
'role': 'participant'
})));
});
// Test that pressing @ brings up all options
const textarea = view.el.querySelector('textarea.chat-textarea');
const at_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 50
};
view.keyPressed(at_event);
textarea.value = '@';
view.keyUp(at_event);
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(3);
expect(view.el.querySelector('.suggestion-box__results li[aria-selected="true"]').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:first-child').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('dick');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('harry');
done();
}).catch(_.partial(console.error, _));
// Test that pressing @ brings up all options
const textarea = view.el.querySelector('textarea.chat-textarea');
const at_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 50,
'key': '@'
};
view.keyPressed(at_event);
textarea.value = '@';
view.keyUp(at_event);
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(3);
expect(view.el.querySelector('.suggestion-box__results li[aria-selected="true"]').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:first-child').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('dick');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('harry');
done();
}));
it("autocompletes when the user presses tab",
......@@ -88,7 +87,8 @@
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 9
'keyCode': 9,
'key': 'Tab'
}
view.keyPressed(tab_event);
view.keyUp(tab_event);
......@@ -168,5 +168,46 @@
expect(textarea.value).toBe('hello @z3r0 ');
done();
}));
it("autocompletes when the user presses backspace",
mock.initConverse(
null, ['rosterGroupsFetched'], {},
async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
const view = _converse.chatboxviews.get('lounge@localhost');
expect(view.model.occupants.length).toBe(1);
const presence = $pres({
'to': 'dummy@localhost/resource',
'from': 'lounge@localhost/some1'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'some1@localhost/resource',
'role': 'participant'
});
_converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.model.occupants.length).toBe(2);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = "hello @some1 ";
// Press backspace
const backspace_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 8,
'key': 'Backspace'
}
view.keyPressed(backspace_event);
textarea.value = "hello @some1"; // Mimic backspace
view.keyUp(backspace_event);
expect(view.el.querySelector('.suggestion-box__results').hidden).toBeFalsy();
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(1);
expect(view.el.querySelector('.suggestion-box__results li').textContent).toBe('some1');
done();
}));
});
}));
......@@ -671,7 +671,7 @@
await test_utils.waitForRoster(_converse, 'current');
test_utils.openControlBox();
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
spyOn(_converse, 'emit');
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length);
......@@ -817,7 +817,7 @@
test_utils.openControlBox();
await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length);
// TODO: only show paused state if the previous state was composing
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
spyOn(_converse, 'emit').and.callThrough();
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
const view = await test_utils.openChatBoxFor(_converse, sender_jid);
......@@ -985,7 +985,7 @@
await test_utils.waitForRoster(_converse, 'current');
test_utils.openControlBox();
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
spyOn(_converse, 'emit');
await test_utils.openChatBoxFor(_converse, sender_jid);
const view = _converse.chatboxviews.get(sender_jid);
......
......@@ -347,7 +347,7 @@
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24:
// http://xmpp.org/extensions/xep-0045.html#enter-pres
// https://xmpp.org/extensions/xep-0045.html#enter-pres
//
/* <presence xmlns="jabber:client" to="jordie.langen@chat.example.org/converse.js-11659299" from="myroom@conference.chat.example.org/jc">
* <x xmlns="http://jabber.org/protocol/muc#user">
......@@ -1219,7 +1219,7 @@
/* Check that an IQ is sent out, asking for the
* configuration form.
* See: // http://xmpp.org/extensions/xep-0045.html#example-163
* See: // https://xmpp.org/extensions/xep-0045.html#example-163
*
* <iq from='crone1@shakespeare.lit/desktop'
* id='config1'
......@@ -1234,7 +1234,7 @@
`</iq>`);
/* Server responds with the configuration form.
* See: // http://xmpp.org/extensions/xep-0045.html#example-165
* See: // https://xmpp.org/extensions/xep-0045.html#example-165
*/
var config_stanza = $iq({from: 'coven@chat.shakespeare.lit',
'id': IQ_id,
......@@ -1398,7 +1398,7 @@
for (var i=0; i<mock.chatroom_names.length; i++) {
name = mock.chatroom_names[i];
role = mock.chatroom_roles[name].role;
// See example 21 http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
jid =
presence = $pres({
to:'dummy@localhost/pda',
......@@ -1418,11 +1418,11 @@
}
// Test users leaving the groupchat
// http://xmpp.org/extensions/xep-0045.html#exit
// https://xmpp.org/extensions/xep-0045.html#exit
for (i=mock.chatroom_names.length-1; i>-1; i--) {
name = mock.chatroom_names[i];
role = mock.chatroom_roles[name].role;
// See example 21 http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
presence = $pres({
to:'dummy@localhost/pda',
from:'lounge@localhost/'+name,
......@@ -1452,7 +1452,7 @@
for (var i=0; i<mock.chatroom_names.length; i++) {
name = mock.chatroom_names[i];
role = mock.chatroom_roles[name].role;
// See example 21 http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
jid =
presence = $pres({
to:'dummy@localhost/pda',
......@@ -1472,11 +1472,11 @@
}
// Test users leaving the groupchat
// http://xmpp.org/extensions/xep-0045.html#exit
// https://xmpp.org/extensions/xep-0045.html#exit
for (i=mock.chatroom_names.length-1; i>-1; i--) {
name = mock.chatroom_names[i];
role = mock.chatroom_roles[name].role;
// See example 21 http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
presence = $pres({
to:'dummy@localhost/pda',
from:'lounge@localhost/'+name,
......@@ -1695,7 +1695,7 @@
// The user has just entered the groupchat (because join was called)
// and receives their own presence from the server.
// See example 24:
// http://xmpp.org/extensions/xep-0045.html#enter-pres
// https://xmpp.org/extensions/xep-0045.html#enter-pres
const presence = $pres({
to:'dummy@localhost/resource',
from:'lounge@localhost/thirdwitch',
......@@ -1946,7 +1946,7 @@
async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'jdev', 'conference.jabber.org', 'jc');
const text = 'Jabber/XMPP Development | RFCs and Extensions: http://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
const text = 'Jabber/XMPP Development | RFCs and Extensions: https://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
let stanza = u.toStanza(`
<message xmlns="jabber:client" to="jc@opkode.com/_converse.js-60429116" type="groupchat" from="jdev@conference.jabber.org/ralphm">
<subject>${text}</subject>
......@@ -2008,7 +2008,7 @@
* nickname and one indicating availability for the new
* nickname.
*
* See: http://xmpp.org/extensions/xep-0045.html#changenick
* See: https://xmpp.org/extensions/xep-0045.html#changenick
*
* <presence
* from='coven@localhost/thirdwitch'
......@@ -4082,7 +4082,7 @@
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
// See: http://xmpp.org/extensions/xep-0045.html#disco-rooms
// See: https://xmpp.org/extensions/xep-0045.html#disco-rooms
expect(modal.el.querySelectorAll('.available-chatrooms li').length).toBe(0);
const server_input = modal.el.querySelector('input[name="server"]');
......@@ -4299,7 +4299,7 @@
expect(sizzle('div.chat-info:last', chat_content).pop().textContent)
.toBe("nomorenicks has entered the groupchat");
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
// <composing> state
let msg = $msg({
......@@ -4368,10 +4368,8 @@
expect(notifications.length).toBe(2);
expect(notifications[0].textContent).toEqual('newguy is typing');
expect(notifications[1].textContent).toEqual('nomorenicks is typing');
expect(timeout_functions.length).toBe(3);
// Check that new messages appear under the chat state
// notifications
// Check that new messages appear under the chat state notifications
msg = $msg({
from: `${room_jid}/some1`,
id: (new Date()).getTime(),
......@@ -4386,8 +4384,7 @@
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg .chat-msg__text').textContent).toBe('hello world');
// Test that the composing notifications get removed
// via timeout.
// Test that the composing notifications get removed via timeout.
timeout_functions[0]();
events = view.el.querySelectorAll('.chat-event');
expect(events.length).toBe(3);
......@@ -4475,7 +4472,7 @@
expect(sizzle('div.chat-info:last', chat_content).pop().textContent)
.toBe("nomorenicks has entered the groupchat");
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
// See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions
// <composing> state
var msg = $msg({
......
......@@ -112,7 +112,7 @@
}).then(stanza => {
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 24: https://xmpp.org/extensions/xep-0045.html#enter-pres
const presence = $pres({
to: _converse.connection.jid,
from: room_jid,
......
......@@ -1270,7 +1270,7 @@
expect(_converse.roster.pluck('jid').length).toBe(1);
expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
// Taken from the spec
// http://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3
// https://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3
stanza = $iq({
to: _converse.connection.jid,
type: 'result',
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......@@ -13,7 +13,6 @@ import converse from "@converse/headless/converse-core";
const { _, Backbone } = converse.env,
u = converse.env.utils;
converse.plugins.add("converse-autocomplete", {
initialize () {
......@@ -73,12 +72,12 @@ converse.plugins.add("converse-autocomplete", {
_.assignIn(this, {
'match_current_word': false, // Match only the current word, otherwise all input is matched
'match_on_tab': false, // Whether matching should only start when tab's pressed
'trigger_on_at': false, // Whether @ should trigger autocomplete
'ac_triggers': [], // Array of keys (`ev.key`) values that will trigger auto-complete
'include_triggers': [], // Array of trigger keys which should be included in the returned value
'min_chars': 2,
'max_items': 10,
'auto_evaluate': true,
'auto_first': false,
'auto_first': false, // Should the first element be automatically selected?
'data': _.identity,
'filter': _converse.FILTER_CONTAINS,
'sort': config.sort === false ? false : SORT_BYLENGTH,
......@@ -291,11 +290,17 @@ converse.plugins.add("converse-autocomplete", {
, ev.keyCode)) {
return;
}
if (this.match_on_tab && ev.keyCode === _converse.keycodes.TAB) {
ev.preventDefault();
this.auto_completing = true;
} else if (this.trigger_on_at && ev.keyCode === _converse.keycodes.AT) {
if (this.ac_triggers.includes(ev.key)) {
if (ev.key === "Tab") {
ev.preventDefault();
}
this.auto_completing = true;
} else if (ev.key === "Backspace") {
const word = u.getCurrentWord(ev.target, ev.target.selectionEnd-1);
if (this.ac_triggers.includes(word[0])) {
this.auto_completing = true;
}
}
}
......@@ -316,7 +321,7 @@ converse.plugins.add("converse-autocomplete", {
let value = this.match_current_word ? u.getCurrentWord(this.input) : this.input.value;
let ignore_min_chars = false;
if (this.trigger_on_at && value.startsWith('@')) {
if (this.ac_triggers.includes(value[0]) && !this.include_triggers.includes(ev.key)) {
ignore_min_chars = true;
value = value.slice('1');
}
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) JC Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......@@ -128,7 +128,7 @@ converse.plugins.add('converse-muc-views', {
return str;
}
/* http://xmpp.org/extensions/xep-0045.html
/* https://xmpp.org/extensions/xep-0045.html
* ----------------------------------------
* 100 message Entering a groupchat Inform user that any occupant is allowed to see the user's full JID
* 101 message (out of band) Affiliation change Inform user that his or her affiliation changed while not in the groupchat
......@@ -206,7 +206,7 @@ converse.plugins.add('converse-muc-views', {
* (XMLElement) stanza: The IQ stanza containing the groupchat
* info.
*/
// All MUC features found here: http://xmpp.org/registrar/disco-features.html
// All MUC features found here: https://xmpp.org/registrar/disco-features.html
el.querySelector('span.spinner').remove();
el.querySelector('a.room-info').classList.add('selected');
el.insertAdjacentHTML(
......@@ -506,7 +506,9 @@ converse.plugins.add('converse-muc-views', {
'click .upload-file': 'toggleFileUpload',
'keydown .chat-textarea': 'keyPressed',
'keyup .chat-textarea': 'keyUp',
'input .chat-textarea': 'inputChanged'
'input .chat-textarea': 'inputChanged',
'dragover .chat-textarea': 'onDragOver',
'drop .chat-textarea': 'onDrop',
},
initialize () {
......@@ -560,7 +562,7 @@ converse.plugins.add('converse-muc-views', {
this.renderHeading();
this.renderChatArea();
this.renderMessageForm();
this.initAutoComplete();
this.initMentionAutoComplete();
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
this.showSpinner();
}
......@@ -587,16 +589,16 @@ converse.plugins.add('converse-muc-views', {
return this;
},
initAutoComplete () {
initMentionAutoComplete () {
this.auto_complete = new _converse.AutoComplete(this.el, {
'auto_first': true,
'auto_evaluate': false,
'min_chars': 1,
'match_current_word': true,
'match_on_tab': true,
'list': () => this.model.occupants.map(o => ({'label': o.getDisplayName(), 'value': `@${o.getDisplayName()}`})),
'filter': _converse.FILTER_STARTSWITH,
'trigger_on_at': true
'ac_triggers': ["Tab", "@"],
'include_triggers': []
});
this.auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false));
},
......@@ -812,7 +814,7 @@ converse.plugins.add('converse-muc-views', {
* ignore <gone/> notifications in groupchats.
*
* As laid out in the business rules in XEP-0085
* http://xmpp.org/extensions/xep-0085.html#bizrules-groupchat
* https://xmpp.org/extensions/xep-0085.html#bizrules-groupchat
*/
if (message.get('fullname') === this.model.get('nick')) {
// Don't know about other servers, but OpenFire sends
......@@ -1669,7 +1671,7 @@ converse.plugins.add('converse-muc-views', {
showStatusMessages (stanza) {
/* Check for status codes and communicate their purpose to the user.
* See: http://xmpp.org/registrar/mucstatus.html
* See: https://xmpp.org/registrar/mucstatus.html
*
* Parameters:
* (XMLElement) stanza: The message or presence stanza
......@@ -1837,9 +1839,7 @@ converse.plugins.add('converse-muc-views', {
const show = this.model.get('show');
return tpl_occupant(
_.extend(
{ '_': _, // XXX Normally this should already be included,
// but with the current webpack build,
// we only get a subset of the _ methods.
{ '_': _,
'jid': '',
'show': show,
'hint_show': _converse.PRETTY_CHAT_STATUS[show],
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, JC Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
......@@ -165,7 +165,7 @@ _converse.TIMEOUTS = { // Set as module attr so that we can override in tests.
};
// XEP-0085 Chat states
// http://xmpp.org/extensions/xep-0085.html
// https://xmpp.org/extensions/xep-0085.html
_converse.INACTIVE = 'inactive';
_converse.ACTIVE = 'active';
_converse.COMPOSING = 'composing';
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse developers
// Licensed under the Mozilla Public License (MPLv2)
......@@ -217,7 +217,7 @@ converse.plugins.add('converse-disco', {
});
function addClientFeatures () {
// See http://xmpp.org/registrar/disco-categories.html
// See https://xmpp.org/registrar/disco-categories.html
_converse.api.disco.own.identities.add('client', 'web', 'Converse');
_converse.api.disco.own.features.add(Strophe.NS.BOSH);
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......@@ -538,7 +538,7 @@ converse.plugins.add('converse-muc', {
/* Send an IQ stanza to the server, asking it for the
* member-list of this groupchat.
*
* See: http://xmpp.org/extensions/xep-0045.html#modifymember
* See: https://xmpp.org/extensions/xep-0045.html#modifymember
*
* Parameters:
* (String) affiliation: The specific member list to
......@@ -559,7 +559,7 @@ converse.plugins.add('converse-muc', {
/* Send IQ stanzas to the server to set an affiliation for
* the provided JIDs.
*
* See: http://xmpp.org/extensions/xep-0045.html#modifymember
* See: https://xmpp.org/extensions/xep-0045.html#modifymember
*
* XXX: Prosody doesn't accept multiple JIDs' affiliations
* being set in one IQ stanza, so as a workaround we send
......@@ -728,7 +728,7 @@ converse.plugins.add('converse-muc', {
/* Send IQ stanzas to the server to modify the
* affiliations in this groupchat.
*
* See: http://xmpp.org/extensions/xep-0045.html#modifymember
* See: https://xmpp.org/extensions/xep-0045.html#modifymember
*
* Parameters:
* (Object) members: A map of jids, affiliations and optionally reasons
......@@ -1498,7 +1498,7 @@ converse.plugins.add('converse-muc', {
* configured automatically. Currently it doesn't make sense to specify
* `roomconfig` values if `auto_configure` is set to `false`.
* For a list of configuration values that can be passed in, refer to these values
* in the [XEP-0045 MUC specification](http://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner).
* in the [XEP-0045 MUC specification](https://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner).
* The values should be named without the `muc#roomconfig_` prefix.
* @param {boolean} [attrs.maximize] A boolean, indicating whether minimized rooms should also be
* maximized, when opened. Set to `false` by default.
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js
// http://conversejs.org
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// This is the internationalization module.
//
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// This is the utilities module.
//
......@@ -332,9 +332,11 @@ u.siblingIndex = function (el) {
return i;
};
u.getCurrentWord = function (input) {
const cursor = input.selectionEnd || undefined;
return _.last(input.value.slice(0, cursor).split(' '));
u.getCurrentWord = function (input, index) {
if (!index) {
index = input.selectionEnd || undefined;
}
return _.last(input.value.slice(0, index).split(' '));
};
u.replaceCurrentWord = function (input, new_value) {
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// This is the utilities module.
//
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// This is the utilities module.
//
......
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
// https://conversejs.org
//
// This is a form utilities module.
//
......@@ -539,89 +539,85 @@ u.xForm2webForm = function (field, stanza, domain) {
* Parameters:
* (XMLElement) field - the field to convert
*/
if (field.getAttribute('type')) {
if (field.getAttribute('type') === 'list-single' ||
field.getAttribute('type') === 'list-multi') {
const values = _.map(
u.queryChildren(field, 'value'),
_.partial(_.get, _, 'textContent')
);
const options = _.map(
u.queryChildren(field, 'option'),
function (option) {
const value = _.get(option.querySelector('value'), 'textContent');
return tpl_select_option({
'value': value,
'label': option.getAttribute('label'),
'selected': _.includes(values, value),
'required': !_.isNil(field.querySelector('required'))
})
}
);
return tpl_form_select({
'id': u.getUniqueId(),
'name': field.getAttribute('var'),
'label': field.getAttribute('label'),
'options': options.join(''),
'multiple': (field.getAttribute('type') === 'list-multi'),
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('type') === 'fixed') {
const text = _.get(field.querySelector('value'), 'textContent');
return '<p class="form-help">'+text+'</p>';
} else if (field.getAttribute('type') === 'jid-multi') {
return tpl_form_textarea({
'name': field.getAttribute('var'),
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent'),
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('type') === 'boolean') {
return tpl_form_checkbox({
'id': u.getUniqueId(),
'name': field.getAttribute('var'),
'label': field.getAttribute('label') || '',
'checked': _.get(field.querySelector('value'), 'textContent') === "1" && 'checked="1"' || '',
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('var') === 'url') {
return tpl_form_url({
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent')
});
} else if (field.getAttribute('var') === 'username') {
return tpl_form_username({
'domain': ' @'+domain,
'name': field.getAttribute('var'),
'type': XFORM_TYPE_MAP[field.getAttribute('type')],
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent'),
'required': !_.isNil(field.querySelector('required'))
});
} else {
return tpl_form_input({
'id': u.getUniqueId(),
'label': field.getAttribute('label') || '',
'name': field.getAttribute('var'),
'placeholder': null,
'required': !_.isNil(field.querySelector('required')),
'type': XFORM_TYPE_MAP[field.getAttribute('type')],
'value': _.get(field.querySelector('value'), 'textContent')
});
}
if (field.getAttribute('type') === 'list-single' ||
field.getAttribute('type') === 'list-multi') {
const values = _.map(
u.queryChildren(field, 'value'),
_.partial(_.get, _, 'textContent')
);
const options = _.map(
u.queryChildren(field, 'option'),
function (option) {
const value = _.get(option.querySelector('value'), 'textContent');
return tpl_select_option({
'value': value,
'label': option.getAttribute('label'),
'selected': _.includes(values, value),
'required': !_.isNil(field.querySelector('required'))
})
}
);
return tpl_form_select({
'id': u.getUniqueId(),
'name': field.getAttribute('var'),
'label': field.getAttribute('label'),
'options': options.join(''),
'multiple': (field.getAttribute('type') === 'list-multi'),
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('type') === 'fixed') {
const text = _.get(field.querySelector('value'), 'textContent');
return '<p class="form-help">'+text+'</p>';
} else if (field.getAttribute('type') === 'jid-multi') {
return tpl_form_textarea({
'name': field.getAttribute('var'),
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent'),
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('type') === 'boolean') {
return tpl_form_checkbox({
'id': u.getUniqueId(),
'name': field.getAttribute('var'),
'label': field.getAttribute('label') || '',
'checked': _.get(field.querySelector('value'), 'textContent') === "1" && 'checked="1"' || '',
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('var') === 'url') {
return tpl_form_url({
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent')
});
} else if (field.getAttribute('var') === 'username') {
return tpl_form_username({
'domain': ' @'+domain,
'name': field.getAttribute('var'),
'type': XFORM_TYPE_MAP[field.getAttribute('type')],
'label': field.getAttribute('label') || '',
'value': _.get(field.querySelector('value'), 'textContent'),
'required': !_.isNil(field.querySelector('required'))
});
} else if (field.getAttribute('var') === 'ocr') { // Captcha
const uri = field.querySelector('uri');
const el = sizzle('data[cid="'+uri.textContent.replace(/^cid:/, '')+'"]', stanza)[0];
return tpl_form_captcha({
'label': field.getAttribute('label'),
'name': field.getAttribute('var'),
'data': _.get(el, 'textContent'),
'type': uri.getAttribute('type'),
'required': !_.isNil(field.querySelector('required'))
});
} else {
if (field.getAttribute('var') === 'ocr') { // Captcha
const uri = field.querySelector('uri');
const el = sizzle('data[cid="'+uri.textContent.replace(/^cid:/, '')+'"]', stanza)[0];
return tpl_form_captcha({
'label': field.getAttribute('label'),
'name': field.getAttribute('var'),
'data': _.get(el, 'textContent'),
'type': uri.getAttribute('type'),
'required': !_.isNil(field.querySelector('required'))
});
}
return tpl_form_input({
'id': u.getUniqueId(),
'label': field.getAttribute('label') || '',
'name': field.getAttribute('var'),
'placeholder': null,
'required': !_.isNil(field.querySelector('required')),
'type': XFORM_TYPE_MAP[field.getAttribute('type')],
'value': _.get(field.querySelector('value'), 'textContent')
});
}
}
export default u;
......@@ -182,7 +182,7 @@
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
// See example 24: https://xmpp.org/extensions/xep-0045.html#enter-pres
var presence = $pres({
to: _converse.connection.jid,
from: `${room_jid}/${nick}`,
......
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