From 3514d6d56b94f30688395e555f055784e461b5d9 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Tue, 31 Oct 2017 23:04:46 +0100 Subject: [PATCH] fixes #316 - Also allow private chats to be opened via URL fragment. - Make sure to clear the URL fragment when the relevant chat is closed. --- CHANGES.md | 5 ++++- docs/source/features.rst | 10 ++++++++++ src/converse-chatboxes.js | 28 ++++++++++++++++++++++++---- src/converse-chatview.js | 3 +++ src/converse-muc.js | 17 ++++++++++++----- src/converse-register.js | 2 +- src/converse-vcard.js | 2 +- 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 26b5f0406..c0b794d61 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/docs/source/features.rst b/docs/source/features.rst index 97dd51cf3..c453c5ffe 100644 --- a/docs/source/features.rst +++ b/docs/source/features.rst @@ -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 ========================= diff --git a/src/converse-chatboxes.js b/src/converse-chatboxes.js index 91fe2ec15..62f6650db 100644 --- a/src/converse-chatboxes.js +++ b/src/converse-chatboxes.js @@ -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( diff --git a/src/converse-chatview.js b/src/converse-chatview.js index 32a842dee..8af8f0c37 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -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. diff --git a/src/converse-muc.js b/src/converse-muc.js index 0fbf12bd7..0f1962e2d 100755 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -356,18 +356,22 @@ _converse.api.promises.add(['roomsPanelRendered', 'roomsAutoJoined']); - function openRoom (room) { + 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(() => { - if (utils.isValidJID(room)) { - _converse.api.rooms.open(room); - } + _converse.api.rooms.open(jid); }); } - _converse.router.route('converse/room?jid=:room', openRoom); + _converse.router.route('converse/room?jid=:jid', openRoom); function openChatRoom (settings, bring_to_foreground) { @@ -1262,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) { diff --git a/src/converse-register.js b/src/converse-register.js index e5ddd0a5c..f29360d6d 100644 --- a/src/converse-register.js +++ b/src/converse-register.js @@ -419,7 +419,7 @@ _converse.connection.reset(); this.showSpinner(); - if (_.includes(["converse/login", "converse/register"], Backbone.History.getFragment())) { + if (_.includes(["converse/login", "converse/register"], Backbone.history.getFragment())) { _converse.router.navigate('', {'replace': true}); } diff --git a/src/converse-vcard.js b/src/converse-vcard.js index b2300b312..1df8f47f7 100644 --- a/src/converse-vcard.js +++ b/src/converse-vcard.js @@ -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); }