Merge branch 'open-room-via-url'
This commit is contained in:
commit
221798e6e1
@ -3,6 +3,7 @@
|
||||
## 3.3.0 (Unreleased)
|
||||
|
||||
### Bugfixes
|
||||
- #800 Could not register successfully in ejabberd 17.01
|
||||
- Don't require `auto_login` to be `true` when using the API to log in.
|
||||
- Moment locale wasn't being set to the value passed via the `i18n` option.
|
||||
- Refetch the roster from the server after reconnection.
|
||||
@ -12,7 +13,9 @@
|
||||
Otherwise connected contacts might not get your presence updates.
|
||||
|
||||
### New Features
|
||||
- #828 Add routing for the `#converse-login` and `#converse-register` URL
|
||||
- #314 Add support for opening chat rooms with a URL fragment such as `#converse/room?jid=room@domain`
|
||||
and private chats with a URL fragment such as `#converse/chat?jid=user@domain`
|
||||
- #828 Add routing for the `#converse/login` and `#converse/register` URL
|
||||
fragments, which will render the registration and login forms respectively.
|
||||
|
||||
### UX/UI changes
|
||||
|
@ -300,6 +300,22 @@ have to be registered anew.
|
||||
|
||||
``_converse.on('reconnected', function () { ... });``
|
||||
|
||||
roomsAutoJoined
|
||||
---------------
|
||||
|
||||
Emitted once any rooms that have been configured to be automatically joined,
|
||||
specified via the _`auto_join_rooms` setting, have been entered.
|
||||
|
||||
``_converse.on('roomsAutoJoined', function () { ... });``
|
||||
|
||||
Also available as an `ES2015 Promise <http://es6-features.org/#PromiseUsage>`_:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
_converse.api.waitUntil('roomsAutoJoined').then(function () {
|
||||
// Your code here...
|
||||
});
|
||||
|
||||
roomInviteSent
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -6,6 +6,16 @@
|
||||
Features
|
||||
========
|
||||
|
||||
Open chats via URL
|
||||
==================
|
||||
|
||||
From version 3.3.0, converse.js now has the ability to open chats (private or
|
||||
groupchat) based on the URL fragment.
|
||||
|
||||
A room (aka groupchat) can be opened with a URL fragment such as `#converse/room?jid=room@domain`
|
||||
and a private chat with a URL fragment such as
|
||||
`#converse/chat?jid=user@domain`.
|
||||
|
||||
Off-the-record encryption
|
||||
=========================
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
define(["converse-core"], factory);
|
||||
}(this, function (converse) {
|
||||
"use strict";
|
||||
const { Backbone, Strophe, b64_sha1, utils, _ } = converse.env;
|
||||
const { Backbone, Promise, Strophe, b64_sha1, utils, _ } = converse.env;
|
||||
|
||||
converse.plugins.add('converse-chatboxes', {
|
||||
|
||||
@ -55,6 +55,23 @@
|
||||
'chatBoxesInitialized'
|
||||
]);
|
||||
|
||||
function openChat (jid) {
|
||||
if (!utils.isValidJID(jid)) {
|
||||
return converse.log(
|
||||
`Invalid JID "${jid}" provided in URL fragment`,
|
||||
Strophe.LogLevel.WARN
|
||||
);
|
||||
}
|
||||
Promise.all([
|
||||
_converse.api.waitUntil('rosterContactsFetched'),
|
||||
_converse.api.waitUntil('chatBoxesFetched')
|
||||
]).then(() => {
|
||||
_converse.api.chats.open(jid);
|
||||
});
|
||||
}
|
||||
_converse.router.route('converse/chat?jid=:jid', openChat);
|
||||
|
||||
|
||||
_converse.ChatBoxes = Backbone.Collection.extend({
|
||||
comparator: 'time_opened',
|
||||
|
||||
@ -343,9 +360,12 @@
|
||||
_converse.log("chats.open: You need to provide at least one JID", Strophe.LogLevel.ERROR);
|
||||
return null;
|
||||
} else if (_.isString(jids)) {
|
||||
return _converse.getViewForChatBox(
|
||||
_converse.chatboxes.getChatBox(jids, true, attrs).trigger('show')
|
||||
);
|
||||
const chatbox = _converse.chatboxes.getChatBox(jids, true, attrs);
|
||||
if (_.isNil(chatbox)) {
|
||||
_converse.log("Could not open chatbox for JID: "+jids);
|
||||
return;
|
||||
}
|
||||
return _converse.getViewForChatBox(chatbox.trigger('show'));
|
||||
}
|
||||
return _.map(jids, (jid) =>
|
||||
_converse.getViewForChatBox(
|
||||
|
@ -836,6 +836,9 @@
|
||||
|
||||
close (ev) {
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
if (Backbone.history.getFragment() === "converse/chat?jid="+this.model.get('jid')) {
|
||||
_converse.router.navigate('');
|
||||
}
|
||||
if (_converse.connection.connected) {
|
||||
// Immediately sending the chat state, because the
|
||||
// model is going to be destroyed afterwards.
|
||||
|
@ -511,7 +511,7 @@
|
||||
if (jid_element.value &&
|
||||
!_converse.locked_domain &&
|
||||
!_converse.default_domain &&
|
||||
_.filter(jid_element.value.split('@')).length < 2) {
|
||||
!utils.isValidJID(jid_element.value)) {
|
||||
jid_element.setCustomValidity(__('Please enter a valid XMPP address'));
|
||||
return false;
|
||||
}
|
||||
@ -550,6 +550,10 @@
|
||||
jid = Strophe.getBareJidFromJid(jid).toLowerCase()+'/'+resource;
|
||||
}
|
||||
}
|
||||
if (_.includes(["converse/login", "converse/register"],
|
||||
Backbone.history.getFragment())) {
|
||||
_converse.router.navigate('', {'replace': true});
|
||||
}
|
||||
_converse.connection.reset();
|
||||
_converse.connection.connect(jid, password, _converse.onConnectStatusChanged);
|
||||
}
|
||||
|
@ -230,6 +230,9 @@
|
||||
}
|
||||
};
|
||||
|
||||
_converse.router = new Backbone.Router();
|
||||
|
||||
|
||||
_converse.initialize = function (settings, callback) {
|
||||
"use strict";
|
||||
settings = !_.isUndefined(settings) ? settings : {};
|
||||
|
@ -353,9 +353,28 @@
|
||||
'toggle_occupants': true
|
||||
},
|
||||
});
|
||||
_converse.api.promises.add('roomsPanelRendered');
|
||||
_converse.api.promises.add(['roomsPanelRendered', 'roomsAutoJoined']);
|
||||
|
||||
_converse.openChatRoom = function (settings, bring_to_foreground) {
|
||||
|
||||
function openRoom (jid) {
|
||||
if (!utils.isValidJID(jid)) {
|
||||
return converse.log(
|
||||
`Invalid JID "${jid}" provided in URL fragment`,
|
||||
Strophe.LogLevel.WARN
|
||||
);
|
||||
}
|
||||
const promises = [_converse.api.waitUntil('roomsAutoJoined')]
|
||||
if (!_converse.allow_bookmarks) {
|
||||
promises.push( _converse.api.waitUntil('bookmarksInitialized'));
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
_converse.api.rooms.open(jid);
|
||||
});
|
||||
}
|
||||
_converse.router.route('converse/room?jid=:jid', openRoom);
|
||||
|
||||
|
||||
function openChatRoom (settings, bring_to_foreground) {
|
||||
/* Opens a chat room, making sure that certain attributes
|
||||
* are correct, for example that the "type" is set to
|
||||
* "chatroom".
|
||||
@ -367,7 +386,7 @@
|
||||
settings.id = settings.jid;
|
||||
settings.box_id = b64_sha1(settings.jid)
|
||||
return _converse.chatboxviews.showChat(settings, bring_to_foreground);
|
||||
};
|
||||
}
|
||||
|
||||
_converse.ChatRoom = _converse.ChatBox.extend({
|
||||
|
||||
@ -823,7 +842,11 @@
|
||||
affiliations = [affiliations];
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const promises = _.map(affiliations, _.partial(this.requestMemberList, this.model.get('jid')));
|
||||
const promises = _.map(
|
||||
affiliations,
|
||||
_.partial(this.requestMemberList, this.model.get('jid'))
|
||||
);
|
||||
|
||||
Promise.all(promises).then(
|
||||
_.flow(this.marshallAffiliationIQs.bind(this), resolve),
|
||||
_.flow(this.marshallAffiliationIQs.bind(this), resolve)
|
||||
@ -1243,6 +1266,9 @@
|
||||
* reason for leaving.
|
||||
*/
|
||||
this.hide();
|
||||
if (Backbone.history.getFragment() === "converse/room?jid="+this.model.get('jid')) {
|
||||
_converse.router.navigate('');
|
||||
}
|
||||
this.occupantsview.model.reset();
|
||||
this.occupantsview.model.browserStorage._clear();
|
||||
if (_converse.connection.connected) {
|
||||
@ -2637,7 +2663,7 @@
|
||||
ev.preventDefault();
|
||||
const data = this.parseRoomDataFromEvent(ev);
|
||||
if (!_.isUndefined(data)) {
|
||||
_converse.openChatRoom(data);
|
||||
openChatRoom(data);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2685,7 +2711,7 @@
|
||||
}
|
||||
}
|
||||
if (result === true) {
|
||||
const chatroom = _converse.openChatRoom({
|
||||
const chatroom = openChatRoom({
|
||||
'jid': room_jid,
|
||||
'password': $x.attr('password')
|
||||
});
|
||||
@ -2724,6 +2750,7 @@
|
||||
Strophe.LogLevel.ERROR);
|
||||
}
|
||||
});
|
||||
_converse.emit('roomsAutoJoined');
|
||||
}
|
||||
_converse.on('chatBoxesFetched', autoJoinRooms);
|
||||
|
||||
@ -2775,9 +2802,9 @@
|
||||
if (_.isUndefined(jids)) {
|
||||
throw new TypeError('rooms.open: You need to provide at least one JID');
|
||||
} else if (_.isString(jids)) {
|
||||
return _converse.getChatRoom(jids, attrs, _converse.openChatRoom);
|
||||
return _converse.getChatRoom(jids, attrs, openChatRoom);
|
||||
}
|
||||
return _.map(jids, _.partial(_converse.getChatRoom, _, attrs, _converse.openChatRoom));
|
||||
return _.map(jids, _.partial(_converse.getChatRoom, _, attrs, openChatRoom));
|
||||
},
|
||||
'get' (jids, attrs, create) {
|
||||
if (_.isString(attrs)) {
|
||||
|
@ -59,7 +59,7 @@
|
||||
// relevant objects or classes.
|
||||
//
|
||||
// New functions which don't exist yet can also be added.
|
||||
|
||||
|
||||
LoginPanel: {
|
||||
|
||||
render: function (cfg) {
|
||||
@ -80,9 +80,6 @@
|
||||
|
||||
ControlBoxView: {
|
||||
|
||||
events: {
|
||||
},
|
||||
|
||||
initialize () {
|
||||
this.__super__.initialize.apply(this, arguments);
|
||||
this.model.on('change:active-form', this.showLoginOrRegisterForm.bind(this))
|
||||
@ -102,7 +99,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
renderRegistrationPanel () {
|
||||
const { _converse } = this.__super__;
|
||||
if (_converse.allow_registration) {
|
||||
@ -149,21 +145,15 @@
|
||||
providers_link: 'https://xmpp.net/directory.php', // Link to XMPP providers shown on registration page
|
||||
});
|
||||
|
||||
_converse.RegistrationRouter = Backbone.Router.extend({
|
||||
|
||||
initialize () {
|
||||
this.route('converse-login', _.partial(this.setActiveForm, 'login'));
|
||||
this.route('converse-register', _.partial(this.setActiveForm, 'register'));
|
||||
},
|
||||
|
||||
setActiveForm (value) {
|
||||
_converse.api.waitUntil('controlboxInitialized').then(() => {
|
||||
const controlbox = _converse.chatboxes.get('controlbox')
|
||||
controlbox.set({'active-form': value});
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
}
|
||||
});
|
||||
const router = new _converse.RegistrationRouter();
|
||||
function setActiveForm (value) {
|
||||
_converse.api.waitUntil('controlboxInitialized').then(() => {
|
||||
const controlbox = _converse.chatboxes.get('controlbox')
|
||||
controlbox.set({'active-form': value});
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
}
|
||||
_converse.router.route('converse/login', _.partial(setActiveForm, 'login'));
|
||||
_converse.router.route('converse/register', _.partial(setActiveForm, 'register'));
|
||||
|
||||
|
||||
_converse.RegisterPanel = Backbone.View.extend({
|
||||
@ -425,11 +415,14 @@
|
||||
);
|
||||
this.abortRegistration();
|
||||
} else if (status_code === Strophe.Status.REGISTERED) {
|
||||
router.navigate(); // Strip the URL fragment
|
||||
_converse.log("Registered successfully.");
|
||||
_converse.connection.reset();
|
||||
this.showSpinner();
|
||||
|
||||
if (_.includes(["converse/login", "converse/register"], Backbone.history.getFragment())) {
|
||||
_converse.router.navigate('', {'replace': true});
|
||||
}
|
||||
|
||||
if (this.fields.password && this.fields.username) {
|
||||
// automatically log the user in
|
||||
_converse.connection.connect(
|
||||
@ -464,7 +457,7 @@
|
||||
form.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
tpl_form_input({
|
||||
'label': key,
|
||||
'label': key,
|
||||
'name': key,
|
||||
'placeholder': key,
|
||||
'required': true,
|
||||
|
@ -31,7 +31,7 @@
|
||||
function (iq, jid) {
|
||||
_converse.log(
|
||||
`Error while retrieving vcard for ${jid}`,
|
||||
Strophe.LogLevel.ERROR
|
||||
Strophe.LogLevel.WARN
|
||||
);
|
||||
_converse.createRequestingContactFromVCard(presence, iq, jid);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="switch-form">
|
||||
<p>{{{ __("Don't have a chat account?") }}}</p>
|
||||
<p><a class="register-account toggle-register-login" href="#converse-register">{{{__("Create an account")}}}</a></p>
|
||||
<p><a class="register-account toggle-register-login" href="#converse/register">{{{__("Create an account")}}}</a></p>
|
||||
</div>
|
||||
|
@ -17,6 +17,6 @@
|
||||
<div class="switch-form">
|
||||
<p>{{{ __("Already have a chat account?") }}}</p>
|
||||
<p>
|
||||
<a class="login-here toggle-register-login" href="#converse-login">{{{__("Log in here")}}}</a>
|
||||
<a class="login-here toggle-register-login" href="#converse/login">{{{__("Log in here")}}}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -266,6 +266,10 @@
|
||||
}
|
||||
};
|
||||
|
||||
u.isValidJID = function (jid) {
|
||||
return _.filter(jid.split('@')).length === 2 && !jid.startsWith('@') && !jid.endsWith('@');
|
||||
};
|
||||
|
||||
u.isSameBareJID = function (jid1, jid2) {
|
||||
return Strophe.getBareJidFromJid(jid1).toLowerCase() ===
|
||||
Strophe.getBareJidFromJid(jid2).toLowerCase();
|
||||
|
Loading…
Reference in New Issue
Block a user