Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
7e515dd4
Commit
7e515dd4
authored
May 20, 2019
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move all MUC joining logic to the model
parent
39363d49
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
63 additions
and
123 deletions
+63
-123
spec/muc.js
spec/muc.js
+11
-11
src/converse-muc-views.js
src/converse-muc-views.js
+13
-74
src/headless/converse-muc.js
src/headless/converse-muc.js
+39
-38
No files found.
spec/muc.js
View file @
7e515dd4
...
...
@@ -307,7 +307,7 @@
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
features_stanza
));
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"
* from="jordie.langen@chat.example.org/converse.js-11659299"
...
...
@@ -344,7 +344,7 @@
const
input
=
await
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
input[name="nick"]
'
));
input
.
value
=
'
nicky
'
;
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)
// and receives their own presence from the server.
...
...
@@ -359,7 +359,7 @@
* </x>
* </presence>
*/
var
presence
=
$pres
({
const
presence
=
$pres
({
to
:
'
dummy@localhost/resource
'
,
from
:
'
lounge@localhost/thirdwitch
'
,
id
:
'
5025e055-036c-4bc5-a227-706e7e352053
'
...
...
@@ -1752,7 +1752,7 @@
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
features_stanza
));
const
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
spyOn
(
view
,
'
join
'
).
and
.
callThrough
();
spyOn
(
view
.
model
,
'
join
'
).
and
.
callThrough
();
/* <iq from='hag66@shakespeare.lit/pda'
* id='getnick1'
...
...
@@ -1795,7 +1795,7 @@
.
c
(
'
identity
'
,
{
'
category
'
:
'
conference
'
,
'
name
'
:
'
thirdwitch
'
,
'
type
'
:
'
text
'
});
_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)
// and receives their own presence from the server.
...
...
@@ -3617,11 +3617,11 @@
.
toBe
(
'
This groupchat requires a password
'
);
// Let's submit the form
spyOn
(
view
,
'
join
'
);
spyOn
(
view
.
model
,
'
join
'
);
const
input_el
=
view
.
el
.
querySelector
(
'
[name="password"]
'
);
input_el
.
value
=
'
secret
'
;
view
.
el
.
querySelector
(
'
input[type=submit]
'
).
click
();
expect
(
view
.
join
).
toHaveBeenCalledWith
(
'
dummy
'
,
'
secret
'
);
expect
(
view
.
model
.
join
).
toHaveBeenCalledWith
(
'
dummy
'
,
'
secret
'
);
done
();
}));
...
...
@@ -3734,12 +3734,12 @@
const
view
=
_converse
.
chatboxviews
.
get
(
groupchat_jid
);
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
// with that nickname
_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
.
id
=
u
.
getUniqueId
();
...
...
@@ -3749,7 +3749,7 @@
.
c
(
'
conflict
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
_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
.
id
=
new
Date
().
getTime
();
...
...
@@ -3758,7 +3758,7 @@
.
c
(
'
error
'
).
attrs
({
'
by
'
:
groupchat_jid
,
'
type
'
:
'
cancel
'
})
.
c
(
'
conflict
'
).
attrs
({
'
xmlns
'
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
presence
));
expect
(
view
.
join
).
toHaveBeenCalledWith
(
'
dummy-4
'
);
expect
(
view
.
model
.
join
).
toHaveBeenCalledWith
(
'
dummy-4
'
);
done
();
}));
...
...
src/converse-muc-views.js
View file @
7e515dd4
...
...
@@ -544,7 +544,7 @@ converse.plugins.add('converse-muc-views', {
this
.
model
.
messages
.
on
(
'
reset
'
,
()
=>
(
this
.
content
.
innerHTML
=
''
));
this
.
model
.
on
(
'
change:affiliation
'
,
this
.
renderHeading
,
this
);
this
.
model
.
on
(
'
change:connection_status
'
,
this
.
afterConnect
ed
,
this
);
this
.
model
.
on
(
'
change:connection_status
'
,
this
.
onConnectionStatusChang
ed
,
this
);
this
.
model
.
on
(
'
change:hidden_occupants
'
,
this
.
updateOccupantsToggle
,
this
);
this
.
model
.
on
(
'
change:jid
'
,
this
.
renderHeading
,
this
);
this
.
model
.
on
(
'
change:name
'
,
this
.
renderHeading
,
this
);
...
...
@@ -580,7 +580,7 @@ converse.plugins.add('converse-muc-views', {
// is a hanging chatbox (i.e. not in the collection anymore).
return
;
}
this
.
populateAndJ
oin
();
this
.
model
.
j
oin
();
}
/**
* Triggered once a groupchat has been opened
...
...
@@ -747,7 +747,7 @@ converse.plugins.add('converse-muc-views', {
/* Override from converse-chatview, specifically to avoid
* the 'active' chat state from being sent out prematurely.
*
* This is instead done in `
afterConnect
ed` below.
* This is instead done in `
onConnectionStatusChang
ed` below.
*/
if
(
u
.
isPersistableModel
(
this
.
model
))
{
this
.
model
.
clearUnreadMsgCounter
();
...
...
@@ -768,10 +768,13 @@ converse.plugins.add('converse-muc-views', {
this
.
afterShown
();
},
afterConnected
()
{
if
(
this
.
model
.
get
(
'
connection_status
'
)
===
converse
.
ROOMSTATUS
.
CONNECTING
)
{
onConnectionStatusChanged
()
{
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
();
}
else
if
(
this
.
model
.
get
(
'
connection_status
'
)
===
converse
.
ROOMSTATUS
.
ENTERED
)
{
}
else
if
(
conn_status
===
converse
.
ROOMSTATUS
.
ENTERED
)
{
this
.
hideSpinner
();
this
.
setChatState
(
_converse
.
ACTIVE
);
this
.
scrollDown
();
...
...
@@ -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
* groupchat configuration.
...
...
@@ -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
)
{
/* When the nickname is already taken, we either render a
* form for the user to choose a new nickname, or we
...
...
@@ -1313,11 +1266,11 @@ converse.plugins.add('converse-muc-views', {
if
(
_converse
.
muc_nickname_from_jid
)
{
const
nick
=
presence
.
getAttribute
(
'
from
'
).
split
(
'
/
'
)[
1
];
if
(
nick
===
_converse
.
getDefaultMUCNickname
())
{
this
.
join
(
nick
+
'
-2
'
);
this
.
model
.
join
(
nick
+
'
-2
'
);
}
else
{
const
del
=
nick
.
lastIndexOf
(
"
-
"
);
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
{
this
.
renderNicknameForm
(
...
...
@@ -1930,7 +1883,7 @@ converse.plugins.add('converse-muc-views', {
submitPassword
(
ev
)
{
ev
.
preventDefault
();
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
);
}
});
...
...
@@ -1968,7 +1921,7 @@ converse.plugins.add('converse-muc-views', {
const
nick_el
=
ev
.
target
.
nick
;
const
nick
=
nick_el
.
value
.
trim
();
if
(
nick
)
{
this
.
chatroomview
.
join
(
nick
);
this
.
chatroomview
.
model
.
join
(
nick
);
this
.
model
.
set
({
'
validation_message
'
:
null
,
'
nickname
'
:
nick
...
...
@@ -2243,20 +2196,6 @@ converse.plugins.add('converse-muc-views', {
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 ************************/
...
...
src/headless/converse-muc.js
View file @
7e515dd4
...
...
@@ -226,6 +226,7 @@ converse.plugins.add('converse-muc', {
!
this
.
get
(
'
reserved_nick
'
)
&&
await
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
MUC_REGISTER
,
this
.
get
(
'
jid
'
)))
{
this
.
occupants
.
fetchMembers
();
this
.
registerNickname
()
}
},
...
...
@@ -320,10 +321,11 @@ converse.plugins.add('converse-muc', {
* @param { String } nick - The user's nickname
* @param { String } password - Optional password, if required by the groupchat.
*/
join
(
nick
,
password
)
{
nick
=
nick
?
nick
:
this
.
get
(
'
nick
'
);
async
join
(
nick
,
password
)
{
nick
=
nick
?
nick
:
await
this
.
getNickname
(
);
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
)
{
// We have restored a groupchat from session storage,
...
...
@@ -843,15 +845,29 @@ converse.plugins.add('converse-muc', {
.
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
* this user has a reserved nickname for this groupchat.
* If so, we'll use that, otherwise we render the nickname form.
* @private
* @method _converse.ChatRoom#
checkFor
ReservedNick
* @returns { promise } A promise which resolves with the res
ponse IQ
* @method _converse.ChatRoom#
get
ReservedNick
* @returns { promise } A promise which resolves with the res
erved nick or null
*/
async
checkFor
ReservedNick
()
{
async
get
ReservedNick
()
{
const
iq
=
await
_converse
.
api
.
sendIQ
(
$iq
({
'
to
'
:
this
.
get
(
'
jid
'
),
...
...
@@ -862,13 +878,8 @@ converse.plugins.add('converse-muc', {
'
node
'
:
'
x-roomuser-item
'
})
);
const
identity_el
=
iq
.
querySelector
(
'
query[node="x-roomuser-item"] identity
'
),
nick
=
identity_el
?
identity_el
.
getAttribute
(
'
name
'
)
:
null
;
this
.
save
({
'
reserved_nick
'
:
nick
,
'
nick
'
:
nick
},
{
'
silent
'
:
true
});
return
iq
;
const
identity_el
=
iq
.
querySelector
(
'
query[node="x-roomuser-item"] identity
'
);
return
identity_el
?
identity_el
.
getAttribute
(
'
name
'
)
:
null
;
},
async
registerNickname
()
{
...
...
@@ -1417,16 +1428,10 @@ converse.plugins.add('converse-muc', {
}
if
(
result
===
true
)
{
const
chatroom
=
openChatRoom
(
room_jid
,
{
'
password
'
:
x_el
.
getAttribute
(
'
password
'
)
});
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
();
}
}
}
};
if
(
_converse
.
allow_muc_invitations
)
{
...
...
@@ -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 ************************/
_converse
.
api
.
listen
.
on
(
'
addClientFeatures
'
,
()
=>
{
...
...
@@ -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 ************************/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment