Commit 506aa331 authored by JC Brand's avatar JC Brand

Wait for promises before opening chats in API methods

parent cb118b9c
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
- New API method `_converse.api.vcard.update`. - New API method `_converse.api.vcard.update`.
- The `contactStatusChanged` event has been renamed to `contactPresenceChanged` - The `contactStatusChanged` event has been renamed to `contactPresenceChanged`
and a event `presenceChanged` is now also triggered on the contact. and a event `presenceChanged` is now also triggered on the contact.
- `_converse.api.chats.open` and `_converse.api.rooms.open` now returns a
`Presence` which resolves with the `Backbone.Model` representing the chat
object.
## UI changes ## UI changes
......
...@@ -76149,17 +76149,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -76149,17 +76149,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
this.model.on('show', this.show, this); this.model.on('show', this.show, this);
this.model.occupants.on('add', this.showJoinNotification, this); this.model.occupants.on('add', this.showJoinNotification, this);
this.model.occupants.on('remove', this.showLeaveNotification, this); this.model.occupants.on('remove', this.showLeaveNotification, this);
this.model.occupants.on('change:show', occupant => { this.model.occupants.on('change:show', this.showJoinOrLeaveNotification, this);
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
});
this.createEmojiPicker(); this.createEmojiPicker();
this.createOccupantsView(); this.createOccupantsView();
this.render().insertIntoDOM(); this.render().insertIntoDOM();
...@@ -76169,8 +76159,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -76169,8 +76159,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const handler = () => { const handler = () => {
if (!u.isPersistableModel(this.model)) { if (!u.isPersistableModel(this.model)) {
// Happens during tests, nothing to do if this // Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the // is a hanging chatbox (i.e. not in the collection anymore).
// collection anymore).
return; return;
} }
...@@ -77047,6 +77036,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -77047,6 +77036,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} }
}, },
showJoinOrLeaveNotification(occupant) {
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
},
showJoinNotification(occupant) { showJoinNotification(occupant) {
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) { if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
return; return;
...@@ -77094,10 +77095,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -77094,10 +77095,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
showLeaveNotification(occupant) { showLeaveNotification(occupant) {
const nick = occupant.get('nick'), const nick = occupant.get('nick'),
stat = occupant.get('status'), stat = occupant.get('status'),
last_el = this.content.lastElementChild, last_el = this.content.lastElementChild;
last_msg_date = last_el.getAttribute('data-isodate');
if (_.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_msg_date).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) { if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_el.getAttribute('data-isodate')).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) {
let message; let message;
if (_.isNil(stat)) { if (_.isNil(stat)) {
...@@ -77128,7 +77128,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -77128,7 +77128,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'data': `data-leave="${nick}"` 'data': `data-leave="${nick}"`
}; };
if (_.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) { if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
last_el.outerHTML = tpl_info(data); last_el.outerHTML = tpl_info(data);
} else { } else {
const el = u.stringToElement(tpl_info(data)); const el = u.stringToElement(tpl_info(data));
...@@ -83843,8 +83843,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -83843,8 +83843,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
xhr.onload = function () { xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) { if (xhr.status >= 200 && xhr.status < 400) {
jed_instance = new Jed(window.JSON.parse(xhr.responseText)); try {
resolve(); const data = window.JSON.parse(xhr.responseText);
jed_instance = new Jed(data);
resolve();
} catch (e) {
xhr.onerror(e);
}
} else { } else {
xhr.onerror(); xhr.onerror();
} }
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
...@@ -13,32 +13,37 @@ ...@@ -13,32 +13,37 @@
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
_converse.minimized_chats.toggleview.model.browserStorage._clear(); _converse.minimized_chats.toggleview.model.browserStorage._clear();
_converse.minimized_chats.initToggle(); _converse.minimized_chats.initToggle();
var contact_jid, chatview; let contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; let chatview;
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
chatview = _converse.chatboxviews.get(contact_jid); .then(() => {
expect(chatview.model.get('minimized')).toBeFalsy(); chatview = _converse.chatboxviews.get(contact_jid);
expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
chatview.el.querySelector('.toggle-chatbox-button').click(); expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy();
expect(chatview.model.get('minimized')).toBeTruthy(); chatview.el.querySelector('.toggle-chatbox-button').click();
expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeTruthy();
expect(_converse.minimized_chats.keys().length).toBe(1); expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy();
expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); expect(_converse.minimized_chats.keys().length).toBe(1);
expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid);
contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
chatview = _converse.chatboxviews.get(contact_jid); return test_utils.openChatBoxFor(_converse, contact_jid);
expect(chatview.model.get('minimized')).toBeFalsy(); }).then(() => {
chatview.el.querySelector('.toggle-chatbox-button').click(); chatview = _converse.chatboxviews.get(contact_jid);
expect(chatview.model.get('minimized')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeFalsy();
expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); chatview.el.querySelector('.toggle-chatbox-button').click();
expect(_converse.minimized_chats.keys().length).toBe(2); expect(chatview.model.get('minimized')).toBeTruthy();
expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy(); expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy();
done(); expect(_converse.minimized_chats.keys().length).toBe(2);
expect(_.includes(_converse.minimized_chats.keys(), contact_jid)).toBeTruthy();
done();
});
})); }));
it("can be toggled to hide or show minimized chats", it("can be toggled to hide or show minimized chats",
...@@ -47,24 +52,26 @@ ...@@ -47,24 +52,26 @@
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
_converse.minimized_chats.toggleview.model.browserStorage._clear(); _converse.minimized_chats.toggleview.model.browserStorage._clear();
_converse.minimized_chats.initToggle(); _converse.minimized_chats.initToggle();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
var chatview = _converse.chatboxviews.get(contact_jid); .then(() => {
expect($(_converse.minimized_chats.el).is(':visible')).toBeFalsy(); const chatview = _converse.chatboxviews.get(contact_jid);
chatview.model.set({'minimized': true}); expect(u.isVisible(_converse.minimized_chats.el)).toBeFalsy();
expect($(_converse.minimized_chats.el).is(':visible')).toBeTruthy(); chatview.model.set({'minimized': true});
expect(_converse.minimized_chats.keys().length).toBe(1); expect(u.isVisible(_converse.minimized_chats.el)).toBeTruthy();
expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid); expect(_converse.minimized_chats.keys().length).toBe(1);
expect($(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')).is(':visible')).toBeTruthy(); expect(_converse.minimized_chats.keys()[0]).toBe(contact_jid);
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy(); expect(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout'))).toBeTruthy();
_converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click(); expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy();
_converse.minimized_chats.el.querySelector('#toggle-minimized-chats').click();
return test_utils.waitUntil(() => u.isVisible(u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')))) return test_utils.waitUntil(() => u.isVisible(_converse.minimized_chats.el.querySelector('.minimized-chats-flyout')));
.then(function () { }).then(() => {
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy(); expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
done(); done();
}); });
......
This diff is collapsed.
...@@ -92,12 +92,14 @@ ...@@ -92,12 +92,14 @@
it("can be sent without a hint", it("can be sent without a hint",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
// XXX: We need to send a presence from the contact, so that we // XXX: We need to send a presence from the contact, so that we
// have a resource, that resource is then queried to see // have a resource, that resource is then queried to see
...@@ -108,9 +110,9 @@ ...@@ -108,9 +110,9 @@
'to': 'dummy@localhost' 'to': 'dummy@localhost'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]))
test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]).then(function () { .then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
spyOn(view, 'onMessageSubmitted').and.callThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
...@@ -167,10 +169,12 @@ ...@@ -167,10 +169,12 @@
it("can be sent with a hint", it("can be sent with a hint",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched');
test_utils.openControlBox(); test_utils.openControlBox();
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
...@@ -183,9 +187,9 @@ ...@@ -183,9 +187,9 @@
'to': 'dummy@localhost' 'to': 'dummy@localhost'
}); });
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]))
test_utils.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]).then(function () { .then(() => {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler'); var spoiler_toggle = view.el.querySelector('.toggle-compose-spoiler');
spoiler_toggle.click(); spoiler_toggle.click();
...@@ -206,17 +210,17 @@ ...@@ -206,17 +210,17 @@
expect(view.onMessageSubmitted).toHaveBeenCalled(); expect(view.onMessageSubmitted).toHaveBeenCalled();
/* Test the XML stanza /* Test the XML stanza
* *
* <message from="dummy@localhost/resource" * <message from="dummy@localhost/resource"
* to="max.frankfurter@localhost" * to="max.frankfurter@localhost"
* type="chat" * type="chat"
* id="4547c38b-d98b-45a5-8f44-b4004dbc335e" * id="4547c38b-d98b-45a5-8f44-b4004dbc335e"
* xmlns="jabber:client"> * xmlns="jabber:client">
* <body>This is the spoiler</body> * <body>This is the spoiler</body>
* <active xmlns="http://jabber.org/protocol/chatstates"/> * <active xmlns="http://jabber.org/protocol/chatstates"/>
* <spoiler xmlns="urn:xmpp:spoiler:0">This is the hint</spoiler> * <spoiler xmlns="urn:xmpp:spoiler:0">This is the hint</spoiler>
* </message>" * </message>"
*/ */
var stanza = _converse.connection.send.calls.argsFor(0)[0].tree(); var stanza = _converse.connection.send.calls.argsFor(0)[0].tree();
var spoiler_el = stanza.querySelector('spoiler[xmlns="urn:xmpp:spoiler:0"]'); var spoiler_el = stanza.querySelector('spoiler[xmlns="urn:xmpp:spoiler:0"]');
......
...@@ -58,16 +58,17 @@ ...@@ -58,16 +58,17 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
let view, modal;
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid)
.then(() => {
const view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
const show_modal_button = view.el.querySelector('.show-user-details-modal'); const show_modal_button = view.el.querySelector('.show-user-details-modal');
expect(u.isVisible(show_modal_button)).toBeTruthy(); expect(u.isVisible(show_modal_button)).toBeTruthy();
show_modal_button.click(); show_modal_button.click();
const modal = view.user_details_modal; modal = view.user_details_modal;
test_utils.waitUntil(() => u.isVisible(modal.el), 2000) return test_utils.waitUntil(() => u.isVisible(modal.el), 2000);
.then(function () { }).then(function () {
spyOn(window, 'confirm').and.returnValue(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(view.model.contact, 'removeFromRoster').and.callFake(function (callback, errback) { spyOn(view.model.contact, 'removeFromRoster').and.callFake(function (callback, errback) {
errback(); errback();
......
...@@ -561,8 +561,7 @@ ...@@ -561,8 +561,7 @@
const handler = () => { const handler = () => {
if (!u.isPersistableModel(this.model)) { if (!u.isPersistableModel(this.model)) {
// Happens during tests, nothing to do if this // Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the // is a hanging chatbox (i.e. not in the collection anymore).
// collection anymore).
return; return;
} }
this.populateAndJoin(); this.populateAndJoin();
......
...@@ -148,8 +148,13 @@ ...@@ -148,8 +148,13 @@
); );
xhr.onload = function () { xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) { if (xhr.status >= 200 && xhr.status < 400) {
jed_instance = new Jed(window.JSON.parse(xhr.responseText)); try {
resolve(); const data = window.JSON.parse(xhr.responseText);
jed_instance = new Jed(data);
resolve();
} catch (e) {
xhr.onerror(e);
}
} else { } else {
xhr.onerror(); xhr.onerror();
} }
......
...@@ -98,8 +98,9 @@ ...@@ -98,8 +98,9 @@
return views; return views;
}; };
utils.openChatBoxFor = function (converse, jid) { utils.openChatBoxFor = function (_converse, jid) {
return converse.roster.get(jid).trigger("open"); _converse.roster.get(jid).trigger("open");
return utils.waitUntil(() => _converse.chatboxviews.get(jid));
}; };
utils.openChatRoomViaModal = function (_converse, jid, nick) { utils.openChatRoomViaModal = function (_converse, jid, nick) {
...@@ -121,64 +122,64 @@ ...@@ -121,64 +122,64 @@
}; };
utils.openChatRoom = function (_converse, room, server, nick) { utils.openChatRoom = function (_converse, room, server, nick) {
_converse.api.rooms.open(`${room}@${server}`); return _converse.api.rooms.open(`${room}@${server}`);
}; };
utils.openAndEnterChatRoom = function (_converse, room, server, nick) { utils.openAndEnterChatRoom = function (_converse, room, server, nick) {
let last_stanza; let last_stanza;
return new Promise(function (resolve, reject) { return new Promise((resolve, reject) => {
_converse.api.rooms.open(`${room}@${server}`); return _converse.api.rooms.open(`${room}@${server}`).then(() => {
const view = _converse.chatboxviews.get((room+'@'+server).toLowerCase()); const view = _converse.chatboxviews.get((room+'@'+server).toLowerCase());
// We pretend this is a new room, so no disco info is returned. // We pretend this is a new room, so no disco info is returned.
let last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree; let last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree;
const IQ_id = last_stanza.getAttribute('id');
const features_stanza = $iq({
'from': room+'@'+server,
'id': IQ_id,
'to': nick+'@'+server,
'type': 'error'
}).c('error', {'type': 'cancel'})
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(utils.createRequest(features_stanza));
utils.waitUntil(() => {
return _.filter(
_converse.connection.IQ_stanzas, (node) => {
const query = node.nodeTree.querySelector('query');
if (query && query.getAttribute('node') === 'x-roomuser-item') {
last_stanza = node.nodeTree;
return true;
}
}).length
}).then(function () {
// The XMPP server returns the reserved nick for this user.
const IQ_id = last_stanza.getAttribute('id'); const IQ_id = last_stanza.getAttribute('id');
const stanza = $iq({ const features_stanza = $iq({
'type': 'result', 'from': room+'@'+server,
'id': IQ_id, 'id': IQ_id,
'from': view.model.get('jid'), 'to': nick+'@'+server,
'to': _converse.connection.jid 'type': 'error'
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'}) }).c('error', {'type': 'cancel'})
.c('identity', {'category': 'conference', 'name': nick, 'type': 'text'}); .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(utils.createRequest(stanza)); _converse.connection._dataRecv(utils.createRequest(features_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
var presence = $pres({
to: _converse.connection.jid,
from: room+'@'+server+'/'+nick,
id: 'DC352437-C019-40EC-B590-AF29E879AF97'
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({
affiliation: 'member',
jid: _converse.bare_jid,
role: 'participant'
}).up()
.c('status').attrs({code:'110'});
_converse.connection._dataRecv(utils.createRequest(presence));
resolve();
utils.waitUntil(() => {
return _.filter(
_converse.connection.IQ_stanzas, (node) => {
const query = node.nodeTree.querySelector('query');
if (query && query.getAttribute('node') === 'x-roomuser-item') {
last_stanza = node.nodeTree;
return true;
}
}).length
}).then(function () {
// The XMPP server returns the reserved nick for this user.
const IQ_id = last_stanza.getAttribute('id');
const stanza = $iq({
'type': 'result',
'id': IQ_id,
'from': view.model.get('jid'),
'to': _converse.connection.jid
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'})
.c('identity', {'category': 'conference', 'name': nick, 'type': 'text'});
_converse.connection._dataRecv(utils.createRequest(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
var presence = $pres({
to: _converse.connection.jid,
from: room+'@'+server+'/'+nick,
id: 'DC352437-C019-40EC-B590-AF29E879AF97'
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({
affiliation: 'member',
jid: _converse.bare_jid,
role: 'participant'
}).up()
.c('status').attrs({code:'110'});
_converse.connection._dataRecv(utils.createRequest(presence));
resolve();
}).catch(_.partial(console.error, _));
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
}; };
......
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