Commit 7e515dd4 authored by JC Brand's avatar JC Brand

Move all MUC joining logic to the model

parent 39363d49
...@@ -307,7 +307,7 @@ ...@@ -307,7 +307,7 @@
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
const view = _converse.chatboxviews.get('lounge@localhost'); const view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').and.callThrough(); spyOn(view.model, 'join').and.callThrough();
/* <iq to="myroom@conference.chat.example.org" /* <iq to="myroom@conference.chat.example.org"
* from="jordie.langen@chat.example.org/converse.js-11659299" * from="jordie.langen@chat.example.org/converse.js-11659299"
...@@ -344,7 +344,7 @@ ...@@ -344,7 +344,7 @@
const input = await test_utils.waitUntil(() => view.el.querySelector('input[name="nick"]')); const input = await test_utils.waitUntil(() => view.el.querySelector('input[name="nick"]'));
input.value = 'nicky'; input.value = 'nicky';
view.el.querySelector('input[type=submit]').click(); view.el.querySelector('input[type=submit]').click();
expect(view.join).toHaveBeenCalled(); expect(view.model.join).toHaveBeenCalled();
// The user has just entered the room (because join was called) // The user has just entered the room (because join was called)
// and receives their own presence from the server. // and receives their own presence from the server.
...@@ -359,7 +359,7 @@ ...@@ -359,7 +359,7 @@
* </x> * </x>
* </presence> * </presence>
*/ */
var presence = $pres({ const presence = $pres({
to:'dummy@localhost/resource', to:'dummy@localhost/resource',
from:'lounge@localhost/thirdwitch', from:'lounge@localhost/thirdwitch',
id:'5025e055-036c-4bc5-a227-706e7e352053' id:'5025e055-036c-4bc5-a227-706e7e352053'
...@@ -1752,7 +1752,7 @@ ...@@ -1752,7 +1752,7 @@
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
const view = _converse.chatboxviews.get('lounge@localhost'); const view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').and.callThrough(); spyOn(view.model, 'join').and.callThrough();
/* <iq from='hag66@shakespeare.lit/pda' /* <iq from='hag66@shakespeare.lit/pda'
* id='getnick1' * id='getnick1'
...@@ -1795,7 +1795,7 @@ ...@@ -1795,7 +1795,7 @@
.c('identity', {'category': 'conference', 'name': 'thirdwitch', 'type': 'text'}); .c('identity', {'category': 'conference', 'name': 'thirdwitch', 'type': 'text'});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(view.join).toHaveBeenCalled(); expect(view.model.join).toHaveBeenCalled();
// The user has just entered the groupchat (because join was called) // The user has just entered the groupchat (because join was called)
// and receives their own presence from the server. // and receives their own presence from the server.
...@@ -3617,11 +3617,11 @@ ...@@ -3617,11 +3617,11 @@
.toBe('This groupchat requires a password'); .toBe('This groupchat requires a password');
// Let's submit the form // Let's submit the form
spyOn(view, 'join'); spyOn(view.model, 'join');
const input_el = view.el.querySelector('[name="password"]'); const input_el = view.el.querySelector('[name="password"]');
input_el.value = 'secret'; input_el.value = 'secret';
view.el.querySelector('input[type=submit]').click(); view.el.querySelector('input[type=submit]').click();
expect(view.join).toHaveBeenCalledWith('dummy', 'secret'); expect(view.model.join).toHaveBeenCalledWith('dummy', 'secret');
done(); done();
})); }));
...@@ -3734,12 +3734,12 @@ ...@@ -3734,12 +3734,12 @@
const view = _converse.chatboxviews.get(groupchat_jid); const view = _converse.chatboxviews.get(groupchat_jid);
spyOn(view, 'showErrorMessage').and.callThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
spyOn(view, 'join').and.callThrough(); spyOn(view.model, 'join').and.callThrough();
// Simulate repeatedly that there's already someone in the groupchat // Simulate repeatedly that there's already someone in the groupchat
// with that nickname // with that nickname
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.join).toHaveBeenCalledWith('dummy-2'); expect(view.model.join).toHaveBeenCalledWith('dummy-2');
attrs.from = `${groupchat_jid}/dummy-2`; attrs.from = `${groupchat_jid}/dummy-2`;
attrs.id = u.getUniqueId(); attrs.id = u.getUniqueId();
...@@ -3749,7 +3749,7 @@ ...@@ -3749,7 +3749,7 @@
.c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.join).toHaveBeenCalledWith('dummy-3'); expect(view.model.join).toHaveBeenCalledWith('dummy-3');
attrs.from = `${groupchat_jid}/dummy-3`; attrs.from = `${groupchat_jid}/dummy-3`;
attrs.id = new Date().getTime(); attrs.id = new Date().getTime();
...@@ -3758,7 +3758,7 @@ ...@@ -3758,7 +3758,7 @@
.c('error').attrs({'by': groupchat_jid, 'type': 'cancel'}) .c('error').attrs({'by': groupchat_jid, 'type': 'cancel'})
.c('conflict').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('conflict').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
_converse.connection._dataRecv(test_utils.createRequest(presence)); _converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.join).toHaveBeenCalledWith('dummy-4'); expect(view.model.join).toHaveBeenCalledWith('dummy-4');
done(); done();
})); }));
......
...@@ -544,7 +544,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -544,7 +544,7 @@ converse.plugins.add('converse-muc-views', {
this.model.messages.on('reset', () => (this.content.innerHTML = '')); this.model.messages.on('reset', () => (this.content.innerHTML = ''));
this.model.on('change:affiliation', this.renderHeading, this); this.model.on('change:affiliation', this.renderHeading, this);
this.model.on('change:connection_status', this.afterConnected, this); this.model.on('change:connection_status', this.onConnectionStatusChanged, this);
this.model.on('change:hidden_occupants', this.updateOccupantsToggle, this); this.model.on('change:hidden_occupants', this.updateOccupantsToggle, this);
this.model.on('change:jid', this.renderHeading, this); this.model.on('change:jid', this.renderHeading, this);
this.model.on('change:name', this.renderHeading, this); this.model.on('change:name', this.renderHeading, this);
...@@ -580,7 +580,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -580,7 +580,7 @@ converse.plugins.add('converse-muc-views', {
// is a hanging chatbox (i.e. not in the collection anymore). // is a hanging chatbox (i.e. not in the collection anymore).
return; return;
} }
this.populateAndJoin(); this.model.join();
} }
/** /**
* Triggered once a groupchat has been opened * Triggered once a groupchat has been opened
...@@ -747,7 +747,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -747,7 +747,7 @@ converse.plugins.add('converse-muc-views', {
/* Override from converse-chatview, specifically to avoid /* Override from converse-chatview, specifically to avoid
* the 'active' chat state from being sent out prematurely. * the 'active' chat state from being sent out prematurely.
* *
* This is instead done in `afterConnected` below. * This is instead done in `onConnectionStatusChanged` below.
*/ */
if (u.isPersistableModel(this.model)) { if (u.isPersistableModel(this.model)) {
this.model.clearUnreadMsgCounter(); this.model.clearUnreadMsgCounter();
...@@ -768,10 +768,13 @@ converse.plugins.add('converse-muc-views', { ...@@ -768,10 +768,13 @@ converse.plugins.add('converse-muc-views', {
this.afterShown(); this.afterShown();
}, },
afterConnected () { onConnectionStatusChanged () {
if (this.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING) { const conn_status = this.model.get('connection_status');
if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
this.renderNicknameForm();
} else if (conn_status === converse.ROOMSTATUS.CONNECTING) {
this.showSpinner(); this.showSpinner();
} else if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) { } else if (conn_status === converse.ROOMSTATUS.ENTERED) {
this.hideSpinner(); this.hideSpinner();
this.setChatState(_converse.ACTIVE); this.setChatState(_converse.ACTIVE);
this.scrollDown(); this.scrollDown();
...@@ -1193,28 +1196,6 @@ converse.plugins.add('converse-muc-views', { ...@@ -1193,28 +1196,6 @@ converse.plugins.add('converse-muc-views', {
} }
}, },
populateAndJoin () {
this.model.occupants.fetchMembers();
this.join();
},
/**
* Join the groupchat.
* @private
* @method _converse.ChatRoomView#join
* @param { String } nick - The user's nickname
* @param { String } password - Optional password, if required by the groupchat
*/
join (nick, password) {
if (!nick && !this.model.get('nick')) {
this.checkForReservedNick();
return this;
}
this.showSpinner();
this.model.join(nick, password);
return this;
},
/** /**
* Renders a form given an IQ stanza containing the current * Renders a form given an IQ stanza containing the current
* groupchat configuration. * groupchat configuration.
...@@ -1273,34 +1254,6 @@ converse.plugins.add('converse-muc-views', { ...@@ -1273,34 +1254,6 @@ converse.plugins.add('converse-muc-views', {
} }
}, },
checkForReservedNick () {
/* User service-discovery to ask the XMPP server whether
* this user has a reserved nickname for this groupchat.
* If so, we'll use that, otherwise we render the nickname form.
*/
this.showSpinner();
this.model.checkForReservedNick()
.then(this.onReservedNickFound.bind(this))
.catch(this.onReservedNickNotFound.bind(this));
},
onReservedNickFound (iq) {
if (this.model.get('nick')) {
this.join();
} else {
this.onReservedNickNotFound();
}
},
onReservedNickNotFound (message) {
const nick = _converse.getDefaultMUCNickname();
if (nick) {
this.join(nick);
} else {
this.renderNicknameForm(message);
}
},
onNicknameClash (presence) { onNicknameClash (presence) {
/* When the nickname is already taken, we either render a /* When the nickname is already taken, we either render a
* form for the user to choose a new nickname, or we * form for the user to choose a new nickname, or we
...@@ -1313,11 +1266,11 @@ converse.plugins.add('converse-muc-views', { ...@@ -1313,11 +1266,11 @@ converse.plugins.add('converse-muc-views', {
if (_converse.muc_nickname_from_jid) { if (_converse.muc_nickname_from_jid) {
const nick = presence.getAttribute('from').split('/')[1]; const nick = presence.getAttribute('from').split('/')[1];
if (nick === _converse.getDefaultMUCNickname()) { if (nick === _converse.getDefaultMUCNickname()) {
this.join(nick + '-2'); this.model.join(nick + '-2');
} else { } else {
const del= nick.lastIndexOf("-"); const del= nick.lastIndexOf("-");
const num = nick.substring(del+1, nick.length); const num = nick.substring(del+1, nick.length);
this.join(nick.substring(0, del+1) + String(Number(num)+1)); this.model.join(nick.substring(0, del+1) + String(Number(num)+1));
} }
} else { } else {
this.renderNicknameForm( this.renderNicknameForm(
...@@ -1930,7 +1883,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -1930,7 +1883,7 @@ converse.plugins.add('converse-muc-views', {
submitPassword (ev) { submitPassword (ev) {
ev.preventDefault(); ev.preventDefault();
const password = this.el.querySelector('input[type=password]').value; const password = this.el.querySelector('input[type=password]').value;
this.chatroomview.join(this.chatroomview.model.get('nick'), password); this.chatroomview.model.join(this.chatroomview.model.get('nick'), password);
this.model.set('validation_message', null); this.model.set('validation_message', null);
} }
}); });
...@@ -1968,7 +1921,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -1968,7 +1921,7 @@ converse.plugins.add('converse-muc-views', {
const nick_el = ev.target.nick; const nick_el = ev.target.nick;
const nick = nick_el.value.trim(); const nick = nick_el.value.trim();
if (nick) { if (nick) {
this.chatroomview.join(nick); this.chatroomview.model.join(nick);
this.model.set({ this.model.set({
'validation_message': null, 'validation_message': null,
'nickname': nick 'nickname': nick
...@@ -2243,20 +2196,6 @@ converse.plugins.add('converse-muc-views', { ...@@ -2243,20 +2196,6 @@ converse.plugins.add('converse-muc-views', {
fetchAndSetMUCDomain(view); fetchAndSetMUCDomain(view);
view.model.on('change:connected', _.partial(fetchAndSetMUCDomain, view)); view.model.on('change:connected', _.partial(fetchAndSetMUCDomain, view));
}); });
function reconnectToChatRooms () {
/* Upon a reconnection event from converse, join again
* all the open groupchats.
*/
_converse.chatboxviews.each(view => {
if (view.model.get('type') === _converse.CHATROOMS_TYPE) {
view.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
view.model.registerHandlers();
view.populateAndJoin();
}
});
}
_converse.api.listen.on('reconnected', reconnectToChatRooms);
/************************ END Event Handlers ************************/ /************************ END Event Handlers ************************/
......
...@@ -226,6 +226,7 @@ converse.plugins.add('converse-muc', { ...@@ -226,6 +226,7 @@ converse.plugins.add('converse-muc', {
!this.get('reserved_nick') && !this.get('reserved_nick') &&
await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'))) { await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'))) {
this.occupants.fetchMembers();
this.registerNickname() this.registerNickname()
} }
}, },
...@@ -320,10 +321,11 @@ converse.plugins.add('converse-muc', { ...@@ -320,10 +321,11 @@ converse.plugins.add('converse-muc', {
* @param { String } nick - The user's nickname * @param { String } nick - The user's nickname
* @param { String } password - Optional password, if required by the groupchat. * @param { String } password - Optional password, if required by the groupchat.
*/ */
join (nick, password) { async join (nick, password) {
nick = nick ? nick : this.get('nick'); nick = nick ? nick : await this.getNickname();
if (!nick) { if (!nick) {
throw new TypeError('join: You need to provide a valid nickname'); u.safeSave(this, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
return this;
} }
if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED) { if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
// We have restored a groupchat from session storage, // We have restored a groupchat from session storage,
...@@ -843,15 +845,29 @@ converse.plugins.add('converse-muc', { ...@@ -843,15 +845,29 @@ converse.plugins.add('converse-muc', {
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
}, },
async getNickname () {
let nick = this.get('nick');
if (!nick) {
try {
nick = await this.getReservedNick();
this.save({'reserved_nick': nick, 'nick': nick}, {'silent': true});
} catch (e) {
nick = _converse.getDefaultMUCNickname();
this.save({'nick': nick}, {'silent': true});
}
}
return nick;
},
/** /**
* Use service-discovery to ask the XMPP server whether * Use service-discovery to ask the XMPP server whether
* this user has a reserved nickname for this groupchat. * this user has a reserved nickname for this groupchat.
* If so, we'll use that, otherwise we render the nickname form. * If so, we'll use that, otherwise we render the nickname form.
* @private * @private
* @method _converse.ChatRoom#checkForReservedNick * @method _converse.ChatRoom#getReservedNick
* @returns { promise } A promise which resolves with the response IQ * @returns { promise } A promise which resolves with the reserved nick or null
*/ */
async checkForReservedNick () { async getReservedNick () {
const iq = await _converse.api.sendIQ( const iq = await _converse.api.sendIQ(
$iq({ $iq({
'to': this.get('jid'), 'to': this.get('jid'),
...@@ -862,13 +878,8 @@ converse.plugins.add('converse-muc', { ...@@ -862,13 +878,8 @@ converse.plugins.add('converse-muc', {
'node': 'x-roomuser-item' 'node': 'x-roomuser-item'
}) })
); );
const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'), const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity');
nick = identity_el ? identity_el.getAttribute('name') : null; return identity_el ? identity_el.getAttribute('name') : null;
this.save({
'reserved_nick': nick,
'nick': nick
}, {'silent': true});
return iq;
}, },
async registerNickname () { async registerNickname () {
...@@ -1417,16 +1428,10 @@ converse.plugins.add('converse-muc', { ...@@ -1417,16 +1428,10 @@ converse.plugins.add('converse-muc', {
} }
if (result === true) { if (result === true) {
const chatroom = openChatRoom(room_jid, {'password': x_el.getAttribute('password') }); const chatroom = openChatRoom(room_jid, {'password': x_el.getAttribute('password') });
if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) { if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
// XXX: Leaky abstraction from views here
if (_converse.chatboxviews) {
_converse.chatboxviews.get(room_jid).join();
} else {
_converse.chatboxes.get(room_jid).join(); _converse.chatboxes.get(room_jid).join();
} }
} }
}
}; };
if (_converse.allow_muc_invitations) { if (_converse.allow_muc_invitations) {
...@@ -1497,24 +1502,6 @@ converse.plugins.add('converse-muc', { ...@@ -1497,24 +1502,6 @@ converse.plugins.add('converse-muc', {
}); });
} }
function fetchRegistrationForm (room_jid, user_jid) {
_converse.api.sendIQ(
$iq({
'from': user_jid,
'to': room_jid,
'type': 'get'
}).c('query', {'xmlns': Strophe.NS.REGISTER})
).then(iq => {
}).catch(iq => {
if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', iq).length) {
this.feedback.set('error', __('Error: the groupchat %1$s does not exist.', this.model.getDisplayName()));
} else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) {
this.feedback.set('error', __("Sorry, you're not allowed to register in this groupchat"));
}
});
}
/************************ BEGIN Event Handlers ************************/ /************************ BEGIN Event Handlers ************************/
_converse.api.listen.on('addClientFeatures', () => { _converse.api.listen.on('addClientFeatures', () => {
...@@ -1539,6 +1526,20 @@ converse.plugins.add('converse-muc', { ...@@ -1539,6 +1526,20 @@ converse.plugins.add('converse-muc', {
} }
}); });
}); });
function reconnectToChatRooms () {
/* Upon a reconnection event from converse, join again
* all the open groupchats.
*/
_converse.chatboxes.each(model => {
if (model.get('type') === _converse.CHATROOMS_TYPE) {
model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
model.registerHandlers();
model.join();
}
});
}
_converse.api.listen.on('reconnected', reconnectToChatRooms);
/************************ END Event Handlers ************************/ /************************ END Event Handlers ************************/
......
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