From 1adc4938a8ad17d024d2c2eec90870791511f813 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Sun, 3 Dec 2017 19:05:36 +0100 Subject: [PATCH] Fetch VCard when starting a chat with someone not in the user's roster --- CHANGES.md | 1 + spec/chatbox.js | 59 ++++++++++++++++++++++++++++++++++++++++ src/converse-chatview.js | 1 - src/converse-vcard.js | 9 +++--- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dce709852..21bdd0630 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ This removes the need for separate `inverse.js` and `converse-mobile.js` builds. Instead the `converse.js` build is now used with `view_mode` set to `fullscreen` and `mobile` respectively. +- Fetch VCard when starting a chat with someone not in the user's roster. ### API changes - New API method `_converse.disco.supports` to check whether a certain diff --git a/spec/chatbox.js b/spec/chatbox.js index d564510de..26f8d91e4 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -13,6 +13,7 @@ var $iq = converse.env.$iq; var $msg = converse.env.$msg; var Strophe = converse.env.Strophe; + var Promise = converse.env.Promise; var moment = converse.env.moment; return describe("Chatboxes", function() { @@ -588,7 +589,65 @@ }); })); + describe("when a chatbox is opened for someone who is not in the roster", function () { + + it("the VCard for that user is fetched and the chatbox updated with the results", + mock.initConverseWithPromises( + null, ['rosterGroupsFetched'], {}, + function (done, _converse) { + + _converse.allow_non_roster_messaging = true; + spyOn(_converse, 'emit').and.callThrough(); + + var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + var vcard_fetched = false; + spyOn(_converse.api.vcard, "get").and.callFake(function () { + vcard_fetched = true; + return Promise.resolve({ + 'fullname': mock.cur_names[0], + 'vcard_updated': moment().format(), + 'jid': sender_jid + }); + }); + var message = 'This is a received message from someone not on the roster'; + var msg = $msg({ + from: sender_jid, + to: _converse.connection.jid, + type: 'chat', + id: (new Date()).getTime() + }).c('body').t(message).up() + .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); + + // We don't already have an open chatbox for this user + expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); + + _converse.chatboxes.onMessage(msg); + expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); + + // Check that the chatbox and its view now exist + var chatbox = _converse.chatboxes.get(sender_jid); + var chatboxview = _converse.chatboxviews.get(sender_jid); + expect(chatbox).toBeDefined(); + expect(chatboxview).toBeDefined(); + // XXX: I don't really like the convention of + // setting "fullname" to the JID if there's + // no fullname. Should ideally be null if + // there's no fullname. + expect(chatbox.get('fullname') === sender_jid); + test_utils.waitUntil(function () { return vcard_fetched; }, 100) + .then(function () { + expect(_converse.api.vcard.get).toHaveBeenCalled(); + return test_utils.waitUntil(function () { + return chatbox.get('fullname') === mock.cur_names[0]; + }, 100); + }).then(function () { + done(); + }); + })); + }); + describe("who is not on the roster", function () { + it("will open a chatbox and be displayed inside it if allow_non_roster_messaging is true", mock.initConverseWithPromises( null, ['rosterGroupsFetched'], {}, diff --git a/src/converse-chatview.js b/src/converse-chatview.js index c2ece792a..c7a5c1676 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -274,7 +274,6 @@ this.model.on('showHelpMessages', this.showHelpMessages, this); this.model.on('sendMessage', this.sendMessage, this); - this.render().renderToolbar().insertHeading().fetchMessages(); utils.refreshWebkit(); _converse.emit('chatBoxOpened', this); diff --git a/src/converse-vcard.js b/src/converse-vcard.js index 6c39c7d68..e234632eb 100644 --- a/src/converse-vcard.js +++ b/src/converse-vcard.js @@ -154,19 +154,20 @@ } }); - const updateVCardForChatBox = function (chatbox) { + _converse.on('chatBoxInitialized', function (chatbox) { if (!_converse.use_vcards || chatbox.model.get('type') === 'headline') { return; } _converse.api.waitUntil('rosterInitialized').then(() => { const jid = chatbox.model.get('jid'), contact = _converse.roster.get(jid); - if ((contact) && (!contact.get('vcard_updated'))) { + if (contact && !contact.get('vcard_updated') || + _.isUndefined(contact) && _converse.allow_non_roster_messaging) { + updateChatBoxFromVCard(_converse, jid); } }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); - }; - _converse.on('chatBoxInitialized', updateVCardForChatBox); + }); _converse.on('initialized', () => { _converse.roster.on("add", (contact) => {