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
1a161ad2
Commit
1a161ad2
authored
Dec 02, 2020
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add api for managing modals
Set passed-in properties on modal
parent
b18cc6bc
Changes
24
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
168 additions
and
136 deletions
+168
-136
karma.conf.js
karma.conf.js
+1
-1
spec/controlbox.js
spec/controlbox.js
+6
-7
spec/mock.js
spec/mock.js
+1
-1
spec/modtools.js
spec/modtools.js
+10
-10
spec/muc.js
spec/muc.js
+11
-11
spec/muclist.js
spec/muclist.js
+1
-1
spec/omemo.js
spec/omemo.js
+1
-1
spec/presence.js
spec/presence.js
+5
-3
spec/protocol.js
spec/protocol.js
+1
-1
spec/user-details-modal.js
spec/user-details-modal.js
+4
-3
src/components/message-body.js
src/components/message-body.js
+2
-7
src/converse-chatview.js
src/converse-chatview.js
+1
-4
src/converse-modal.js
src/converse-modal.js
+75
-19
src/converse-muc-views.js
src/converse-muc-views.js
+11
-27
src/converse-profile.js
src/converse-profile.js
+3
-12
src/converse-roomslist.js
src/converse-roomslist.js
+1
-5
src/converse-rosterview.js
src/converse-rosterview.js
+1
-4
src/modals/alert.js
src/modals/alert.js
+1
-0
src/modals/base.js
src/modals/base.js
+9
-3
src/modals/confirm.js
src/modals/confirm.js
+1
-0
src/modals/image.js
src/modals/image.js
+2
-0
src/modals/message-versions.js
src/modals/message-versions.js
+1
-1
src/modals/moderator-tools.js
src/modals/moderator-tools.js
+1
-0
src/modals/user-details.js
src/modals/user-details.js
+18
-15
No files found.
karma.conf.js
View file @
1a161ad2
...
...
@@ -24,6 +24,7 @@ module.exports = function(config) {
{
pattern
:
"
node_modules/sinon/pkg/sinon.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/mock.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/user-details-modal.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/spoilers.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/emojis.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/muclist.js
"
,
type
:
'
module
'
},
...
...
@@ -44,7 +45,6 @@ module.exports = function(config) {
{
pattern
:
"
spec/controlbox.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/roster.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/chatbox.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/user-details-modal.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/messages.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/corrections.js
"
,
type
:
'
module
'
},
{
pattern
:
"
spec/styling.js
"
,
type
:
'
module
'
},
...
...
spec/controlbox.js
View file @
1a161ad2
...
...
@@ -154,8 +154,7 @@ describe("The Controlbox", function () {
await
mock
.
openControlBox
(
_converse
);
var
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.change-status
'
).
click
()
var
modal
=
_converse
.
xmppstatusview
.
status_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
modal-status-change
'
);
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
view
=
_converse
.
xmppstatusview
;
modal
.
el
.
querySelector
(
'
label[for="radio-busy"]
'
).
click
();
// Change status to "dnd"
...
...
@@ -183,7 +182,7 @@ describe("The Controlbox", function () {
await
mock
.
openControlBox
(
_converse
);
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.change-status
'
).
click
()
const
modal
=
_converse
.
xmppstatusview
.
status_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
modal-status-change
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
view
=
_converse
.
xmppstatusview
;
...
...
@@ -219,7 +218,7 @@ describe("The 'Add Contact' widget", function () {
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.add-contact
'
).
click
()
const
modal
=
_converse
.
rosterview
.
add_contact_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-contact-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
expect
(
modal
.
el
.
querySelector
(
'
form.add-xmpp-contact
'
)).
not
.
toBe
(
null
);
...
...
@@ -252,7 +251,7 @@ describe("The 'Add Contact' widget", function () {
mock
.
openControlBox
(
_converse
);
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.add-contact
'
).
click
()
const
modal
=
_converse
.
rosterview
.
add_contact_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-contact-modal
'
)
;
expect
(
modal
.
jid_auto_complete
).
toBe
(
undefined
);
expect
(
modal
.
name_auto_complete
).
toBe
(
undefined
);
...
...
@@ -299,7 +298,7 @@ describe("The 'Add Contact' widget", function () {
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.add-contact
'
).
click
()
const
modal
=
_converse
.
rosterview
.
add_contact_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-contact-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
// We only have autocomplete for the name input
...
...
@@ -369,7 +368,7 @@ describe("The 'Add Contact' widget", function () {
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.add-contact
'
).
click
()
modal
=
_converse
.
rosterview
.
add_contact_modal
;
modal
=
_converse
.
api
.
modal
.
get
(
'
add-contact-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
expect
(
modal
.
jid_auto_complete
).
toBe
(
undefined
);
...
...
spec/mock.js
View file @
1a161ad2
...
...
@@ -152,7 +152,7 @@ window.addEventListener('converse-loaded', () => {
const
roomspanel
=
view
.
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1500
)
modal
.
el
.
querySelector
(
'
input[name="chatroom"]
'
).
value
=
jid
;
if
(
nick
)
{
...
...
spec/modtools.js
View file @
1a161ad2
/*global mock */
/*global mock
, converse
*/
const
_
=
converse
.
env
.
_
;
const
$iq
=
converse
.
env
.
$iq
;
...
...
@@ -8,13 +8,13 @@ const Strophe = converse.env.Strophe;
const
u
=
converse
.
env
.
utils
;
async
function
openModtools
(
view
)
{
async
function
openModtools
(
_converse
,
view
)
{
const
textarea
=
view
.
el
.
querySelector
(
'
.chat-textarea
'
);
textarea
.
value
=
'
/modtools
'
;
const
enter
=
{
'
target
'
:
textarea
,
'
preventDefault
'
:
function
preventDefault
()
{},
'
keyCode
'
:
13
};
view
.
onKeyDown
(
enter
);
await
u
.
waitUntil
(()
=>
view
.
showModeratorToolsModal
.
calls
.
count
());
const
modal
=
view
.
modtools_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
converse-modtools-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
return
modal
;
}
...
...
@@ -40,7 +40,7 @@ describe("The groupchat moderator tool", function () {
const
view
=
_converse
.
chatboxviews
.
get
(
muc_jid
);
await
u
.
waitUntil
(()
=>
(
view
.
model
.
occupants
.
length
===
5
),
1000
);
const
modal
=
await
openModtools
(
view
);
const
modal
=
await
openModtools
(
_converse
,
view
);
let
tab
=
modal
.
el
.
querySelector
(
'
#affiliations-tab
'
);
// Clear so that we don't match older stanzas
_converse
.
connection
.
IQ_stanzas
=
[];
...
...
@@ -163,7 +163,7 @@ describe("The groupchat moderator tool", function () {
// Clear so that we don't match older stanzas
_converse
.
connection
.
IQ_stanzas
=
[];
const
modal
=
await
openModtools
(
view
);
const
modal
=
await
openModtools
(
_converse
,
view
);
const
select
=
modal
.
el
.
querySelector
(
'
.select-affiliation
'
);
expect
(
select
.
value
).
toBe
(
'
owner
'
);
select
.
value
=
'
member
'
;
...
...
@@ -270,7 +270,7 @@ describe("The groupchat moderator tool", function () {
view
.
onKeyDown
(
enter
);
await
u
.
waitUntil
(()
=>
view
.
showModeratorToolsModal
.
calls
.
count
());
const
modal
=
view
.
modtools_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
converse-modtools-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
tab
=
modal
.
el
.
querySelector
(
'
#roles-tab
'
);
...
...
@@ -326,7 +326,7 @@ describe("The groupchat moderator tool", function () {
await
mock
.
openAndEnterChatRoom
(
_converse
,
muc_jid
,
'
romeo
'
,
[],
members
);
const
view
=
_converse
.
chatboxviews
.
get
(
muc_jid
);
await
u
.
waitUntil
(()
=>
(
view
.
model
.
occupants
.
length
===
5
));
const
modal
=
await
openModtools
(
view
);
const
modal
=
await
openModtools
(
_converse
,
view
);
const
tab
=
modal
.
el
.
querySelector
(
'
#affiliations-tab
'
);
// Clear so that we don't match older stanzas
_converse
.
connection
.
IQ_stanzas
=
[];
...
...
@@ -375,7 +375,7 @@ describe("The groupchat moderator tool", function () {
await
mock
.
openAndEnterChatRoom
(
_converse
,
muc_jid
,
'
romeo
'
,
[],
members
);
const
view
=
_converse
.
chatboxviews
.
get
(
muc_jid
);
await
u
.
waitUntil
(()
=>
(
view
.
model
.
occupants
.
length
===
2
));
const
modal
=
await
openModtools
(
view
);
const
modal
=
await
openModtools
(
_converse
,
view
);
// Clear so that we don't match older stanzas
_converse
.
connection
.
IQ_stanzas
=
[];
...
...
@@ -443,7 +443,7 @@ describe("The groupchat moderator tool", function () {
await
mock
.
openAndEnterChatRoom
(
_converse
,
muc_jid
,
'
romeo
'
,
[],
members
);
const
view
=
_converse
.
chatboxviews
.
get
(
muc_jid
);
await
u
.
waitUntil
(()
=>
(
view
.
model
.
occupants
.
length
===
3
));
const
modal
=
await
openModtools
(
view
);
const
modal
=
await
openModtools
(
_converse
,
view
);
const
tab
=
modal
.
el
.
querySelector
(
'
#affiliations-tab
'
);
// Clear so that we don't match older stanzas
_converse
.
connection
.
IQ_stanzas
=
[];
...
...
@@ -481,7 +481,7 @@ describe("The groupchat moderator tool", function () {
view
.
onKeyDown
(
enter
);
await
u
.
waitUntil
(()
=>
view
.
showModeratorToolsModal
.
calls
.
count
());
const
modal
=
view
.
modtools_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
converse-modtools-modal
'
)
;
const
occupant
=
view
.
model
.
occupants
.
findWhere
({
'
jid
'
:
_converse
.
bare_jid
});
expect
(
modal
.
getAssignableAffiliations
(
occupant
)).
toEqual
([
'
owner
'
,
'
admin
'
,
'
member
'
,
'
outcast
'
,
'
none
'
]);
...
...
spec/muc.js
View file @
1a161ad2
...
...
@@ -1973,7 +1973,7 @@ describe("Groupchats", function () {
await
u
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
.open-invite-modal
'
));
view
.
el
.
querySelector
(
'
.open-invite-modal
'
).
click
();
const
modal
=
view
.
muc_invite_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
muc-invite-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
expect
(
modal
.
el
.
querySelectorAll
(
'
#invitee_jids
'
).
length
).
toBe
(
1
);
...
...
@@ -2456,7 +2456,7 @@ describe("Groupchats", function () {
const
info_el
=
view
.
el
.
querySelector
(
"
.show-room-details-modal
"
);
info_el
.
click
();
const
modal
=
view
.
model
.
room_details_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
room-details-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
let
features_list
=
modal
.
el
.
querySelector
(
'
.features-list
'
);
...
...
@@ -4629,7 +4629,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
let
label_name
=
modal
.
el
.
querySelector
(
'
label[for="chatroom"]
'
);
...
...
@@ -4670,7 +4670,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
const
name_input
=
modal
.
el
.
querySelector
(
'
input[name="chatroom"]
'
);
name_input
.
value
=
'
lounge@montague.lit
'
;
...
...
@@ -4693,7 +4693,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
const
label_nick
=
modal
.
el
.
querySelector
(
'
label[for="nickname"]
'
);
expect
(
label_nick
.
textContent
.
trim
()).
toBe
(
'
Nickname:
'
);
...
...
@@ -4712,7 +4712,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
const
label_nick
=
modal
.
el
.
querySelector
(
'
label[for="nickname"]
'
);
expect
(
label_nick
.
textContent
.
trim
()).
toBe
(
'
Nickname:
'
);
...
...
@@ -4729,7 +4729,7 @@ describe("Groupchats", function () {
await
mock
.
openControlBox
(
_converse
);
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
expect
(
modal
.
el
.
querySelector
(
'
.modal-title
'
).
textContent
.
trim
()).
toBe
(
'
Enter a new Groupchat
'
);
spyOn
(
_converse
.
ChatRoom
.
prototype
,
'
getDiscoInfo
'
).
and
.
callFake
(()
=>
Promise
.
resolve
());
...
...
@@ -4769,7 +4769,7 @@ describe("Groupchats", function () {
await
mock
.
openControlBox
(
_converse
);
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-add-muc-modal
'
).
click
();
const
modal
=
roomspanel
.
add_room_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-chatroom-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
)
expect
(
modal
.
el
.
querySelector
(
'
.modal-title
'
).
textContent
.
trim
()).
toBe
(
'
Enter a new Groupchat
'
);
spyOn
(
_converse
.
ChatRoom
.
prototype
,
'
getDiscoInfo
'
).
and
.
callFake
(()
=>
Promise
.
resolve
());
...
...
@@ -4812,7 +4812,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-list-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
muc_list_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
list-chatrooms-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
spyOn
(
_converse
.
ChatRoom
.
prototype
,
'
getDiscoInfo
'
).
and
.
callFake
(()
=>
Promise
.
resolve
());
roomspanel
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
...
...
@@ -4889,7 +4889,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-list-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
muc_list_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
list-chatrooms-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
server_input
=
modal
.
el
.
querySelector
(
'
input[name="server"]
'
);
expect
(
server_input
.
value
).
toBe
(
'
muc.example.org
'
);
...
...
@@ -4906,7 +4906,7 @@ describe("Groupchats", function () {
const
roomspanel
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
).
roomspanel
;
roomspanel
.
el
.
querySelector
(
'
.show-list-muc-modal
'
).
click
();
mock
.
closeControlBox
(
_converse
);
const
modal
=
roomspanel
.
muc_list_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
list-chatrooms-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
spyOn
(
_converse
.
ChatRoom
.
prototype
,
'
getDiscoInfo
'
).
and
.
callFake
(()
=>
Promise
.
resolve
());
roomspanel
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
...
...
spec/muclist.js
View file @
1a161ad2
...
...
@@ -204,7 +204,7 @@ describe("A groupchat shown in the groupchats list", function () {
const
info_el
=
_converse
.
rooms_list_view
.
el
.
querySelector
(
"
.room-info
"
);
info_el
.
click
();
const
modal
=
view
.
model
.
room_details_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
room-details-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
let
els
=
modal
.
el
.
querySelectorAll
(
'
p.room-info
'
);
expect
(
els
[
0
].
textContent
).
toBe
(
"
Name: A Dark Cave
"
)
...
...
spec/omemo.js
View file @
1a161ad2
...
...
@@ -1463,7 +1463,7 @@ describe("The OMEMO module", function() {
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
show_modal_button
.
click
();
const
modal
=
view
.
user_details_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
user-details-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
let
iq_stanza
=
await
u
.
waitUntil
(()
=>
deviceListFetched
(
_converse
,
contact_jid
));
expect
(
Strophe
.
serialize
(
iq_stanza
)).
toBe
(
...
...
spec/presence.js
View file @
1a161ad2
/*global mock */
/*global mock, converse */
// See: https://xmpp.org/rfcs/rfc3921.html
const
original_timeout
=
jasmine
.
DEFAULT_TIMEOUT_INTERVAL
;
...
...
@@ -76,7 +77,7 @@ describe("A sent presence stanza", function () {
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
const
change_status_el
=
await
u
.
waitUntil
(()
=>
cbview
.
el
.
querySelector
(
'
.change-status
'
));
change_status_el
.
click
()
const
modal
=
_converse
.
xmppstatusview
.
status_modal
;
let
modal
=
_converse
.
api
.
modal
.
get
(
'
modal-status-change
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
msg
=
'
My custom status
'
;
modal
.
el
.
querySelector
(
'
input[name="status_message"]
'
).
value
=
msg
;
...
...
@@ -90,10 +91,11 @@ describe("A sent presence stanza", function () {
`<priority>0</priority>`
+
`<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`
+
`</presence>`
)
await
u
.
waitUntil
(()
=>
modal
.
el
.
getAttribute
(
'
aria-hidden
'
)
===
"
true
"
);
await
u
.
waitUntil
(()
=>
!
u
.
isVisible
(
modal
.
el
));
cbview
.
el
.
querySelector
(
'
.change-status
'
).
click
()
modal
=
_converse
.
api
.
modal
.
get
(
'
modal-status-change
'
);
await
u
.
waitUntil
(()
=>
modal
.
el
.
getAttribute
(
'
aria-hidden
'
)
===
"
false
"
,
1000
);
modal
.
el
.
querySelector
(
'
label[for="radio-busy"]
'
).
click
();
// Change status to "dnd"
modal
.
el
.
querySelector
(
'
[type="submit"]
'
).
click
();
...
...
spec/protocol.js
View file @
1a161ad2
...
...
@@ -66,7 +66,7 @@ describe("The Protocol", function () {
});
cbview
.
el
.
querySelector
(
'
.add-contact
'
).
click
()
const
modal
=
_converse
.
rosterview
.
add_contact_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
add-contact-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
spyOn
(
modal
,
"
addContactFromForm
"
).
and
.
callThrough
();
modal
.
delegateEvents
();
...
...
spec/user-details-modal.js
View file @
1a161ad2
...
...
@@ -18,7 +18,7 @@ describe("The User Details Modal", function () {
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
let
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
show_modal_button
.
click
();
const
modal
=
view
.
user_details_modal
;
const
modal
=
_converse
.
api
.
modal
.
get
(
'
user-details-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
spyOn
(
window
,
'
confirm
'
).
and
.
returnValue
(
true
);
spyOn
(
view
.
model
.
contact
,
'
removeFromRoster
'
).
and
.
callFake
(
callback
=>
callback
());
...
...
@@ -45,7 +45,7 @@ describe("The User Details Modal", function () {
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
let
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
show_modal_button
.
click
();
const
modal
=
view
.
user_details_modal
;
let
modal
=
_converse
.
api
.
modal
.
get
(
'
user-details-modal
'
)
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
2000
);
spyOn
(
window
,
'
confirm
'
).
and
.
returnValue
(
true
);
...
...
@@ -53,7 +53,7 @@ describe("The User Details Modal", function () {
let
remove_contact_button
=
modal
.
el
.
querySelector
(
'
button.remove-contact
'
);
expect
(
u
.
isVisible
(
remove_contact_button
)).
toBeTruthy
();
remove_contact_button
.
click
();
await
u
.
waitUntil
(()
=>
!
u
.
isVisible
(
modal
.
el
))
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
document
.
querySelector
(
'
.alert-danger
'
)),
2000
);
const
header
=
document
.
querySelector
(
'
.alert-danger .modal-title
'
);
...
...
@@ -63,6 +63,7 @@ describe("The User Details Modal", function () {
document
.
querySelector
(
'
.alert-danger button.close
'
).
click
();
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
show_modal_button
.
click
();
modal
=
_converse
.
api
.
modal
.
get
(
'
user-details-modal
'
);
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
2000
)
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
...
...
src/components/message-body.js
View file @
1a161ad2
...
...
@@ -15,14 +15,9 @@ export default class MessageBody extends CustomElement {
}
}
showImageModal
(
ev
)
{
showImageModal
(
ev
)
{
// eslint-disable-line class-methods-use-this
ev
.
preventDefault
();
if
(
this
.
image_modal
===
undefined
)
{
this
.
image_modal
=
new
ImageModal
();
}
this
.
image_modal
.
src
=
ev
.
target
.
src
;
this
.
image_modal
.
render
();
this
.
image_modal
.
show
(
ev
);
api
.
modal
.
create
(
ImageModal
,
{
'
src
'
:
ev
.
target
.
src
},
ev
).
show
(
ev
);
}
render
()
{
...
...
src/converse-chatview.js
View file @
1a161ad2
...
...
@@ -238,10 +238,7 @@ export const ChatBoxView = View.extend({
showUserDetailsModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
user_details_modal
===
undefined
)
{
this
.
user_details_modal
=
new
UserDetailsModal
({
model
:
this
.
model
});
}
this
.
user_details_modal
.
show
(
ev
);
api
.
modal
.
show
(
UserDetailsModal
,
{
model
:
this
.
model
},
ev
);
},
onDragOver
(
evt
)
{
...
...
src/converse-modal.js
View file @
1a161ad2
...
...
@@ -7,15 +7,77 @@ import Alert from './modals/alert.js';
import
BootstrapModal
from
'
./modals/base.js
'
;
import
Confirm
from
'
./modals/confirm.js
'
;
import
{
Model
}
from
'
@converse/skeletor/src/model.js
'
;
import
{
_converse
,
converse
}
from
"
@converse/headless/converse-core
"
;
import
{
_converse
,
api
,
converse
}
from
"
@converse/headless/converse-core
"
;
converse
.
env
.
BootstrapModal
=
BootstrapModal
;
// expose to plugins
let
alert
;
let
modals
=
[];
const
modal_api
=
{
/**
* API namespace for methods relating to modals
* @namespace _converse.api.modal
* @memberOf _converse.api
*/
modal
:
{
/**
* Shows a modal of type `ModalClass` to the user.
* Will create a new instance of that class if an existing one isn't
* found.
* @param { Class } ModalClass
* @param { [Object] } properties - Optional properties that will be
* set on a newly created modal instance (if no pre-existing modal was
* found).
* @param { [Event] } event - The DOM event that causes the modal to be shown.
*/
show
(
ModalClass
,
properties
,
ev
)
{
const
modal
=
this
.
get
(
ModalClass
.
id
)
||
this
.
create
(
ModalClass
,
properties
);
modal
.
show
(
ev
);
return
modal
;
},
/**
* Return a modal with the passed-in identifier, if it exists.
* @param { String } id
*/
get
(
id
)
{
return
modals
.
filter
(
m
=>
m
.
id
==
id
).
pop
();
},
/**
* Create a modal of the passed-in type.
* @param { Class } ModalClass
* @param { [Object] } properties - Optional properties that will be
* set on the modal instance.
*/
create
(
ModalClass
,
properties
)
{
const
modal
=
new
ModalClass
(
properties
);
modals
.
push
(
modal
);
return
modal
;
},
/**
* Remove a particular modal
* @param { View } modal
*/
remove
(
modal
)
{
modals
=
modals
.
filter
(
m
=>
m
!==
modal
);
modal
.
remove
();
},
/**
* Remove all modals
*/
removeAll
()
{
modals
.
forEach
(
m
=>
m
.
remove
());
modals
=
[];
}
},
/**
* Show a confirm modal to the user.
* @method _converse.api.confirm
...
...
@@ -101,22 +163,13 @@ const modal_api = {
level
=
'
alert-warning
'
;
}
if
(
alert
===
undefined
)
{
const
model
=
new
Model
({
'
title
'
:
title
,
'
messages
'
:
messages
,
'
level
'
:
level
,
'
type
'
:
'
alert
'
})
alert
=
new
Alert
({
model
});
}
else
{
alert
.
model
.
set
({
'
title
'
:
title
,
'
messages
'
:
messages
,
'
level
'
:
level
});
}
alert
.
show
();
api
.
modal
.
show
(
Alert
,
{
model
});
}
}
...
...
@@ -124,12 +177,15 @@ const modal_api = {
converse
.
plugins
.
add
(
'
converse-modal
'
,
{
initialize
()
{
_converse
.
api
.
listen
.
on
(
'
disconnect
'
,
()
=>
{
api
.
listen
.
on
(
'
disconnect
'
,
()
=>
{
const
container
=
document
.
querySelector
(
"
#converse-modals
"
);
if
(
container
)
{
container
.
innerHTML
=
''
;
}
});
api
.
listen
.
on
(
'
clearSession
'
,
()
=>
api
.
modal
.
removeAll
());
Object
.
assign
(
_converse
.
api
,
modal_api
);
}
});
src/converse-muc-views.js
View file @
1a161ad2
...
...
@@ -501,29 +501,24 @@ export const ChatRoomView = ChatBoxView.extend({
if
(
!
this
.
verifyRoles
([
'
moderator
'
]))
{
return
;
}
if
(
typeof
this
.
model
.
modtools_modal
===
'
undefined
'
)
{
const
model
=
new
Model
({
'
affiliation
'
:
affiliation
});
this
.
modtools_modal
=
new
ModeratorToolsModal
({
model
,
_converse
,
'
chatroomview
'
:
this
}
);
let
modal
=
api
.
modal
.
get
(
ModeratorToolsModal
.
id
);
if
(
modal
)
{
modal
.
model
.
set
(
'
affiliation
'
,
affiliation
);
}
else
{
this
.
modtools_modal
.
set
(
'
affiliation
'
,
affiliation
);
const
model
=
new
Model
({
'
affiliation
'
:
affiliation
});
modal
=
api
.
modal
.
create
(
ModeratorToolsModal
,
{
model
,
_converse
,
'
chatroomview
'
:
this
});
}
this
.
modtools_
modal
.
show
();
modal
.
show
();
},
showRoomDetailsModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
model
.
room_details_modal
===
undefined
)
{
this
.
model
.
room_details_modal
=
new
RoomDetailsModal
({
'
model
'
:
this
.
model
});
}
this
.
model
.
room_details_modal
.
show
(
ev
);
api
.
modal
.
show
(
RoomDetailsModal
,
{
'
model
'
:
this
.
model
},
ev
);
},
showOccupantDetailsModal
(
ev
,
message
)
{
ev
.
preventDefault
();
if
(
this
.
model
.
occupant_modal
===
undefined
)
{
this
.
model
.
occupant_modal
=
new
OccupantModal
({
'
model
'
:
message
.
occupant
});
}
this
.
model
.
occupant_modal
.
show
(
ev
);
api
.
modal
.
show
(
OccupantModal
,
{
'
model
'
:
message
.
occupant
},
ev
);
},
showChatStateNotification
(
message
)
{
...
...
@@ -679,12 +674,7 @@ export const ChatRoomView = ChatBoxView.extend({
showInviteModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
muc_invite_modal
===
undefined
)
{
this
.
muc_invite_modal
=
new
MUCInviteModal
({
'
model
'
:
new
Model
()});
// TODO: remove once we have API for sending direct invite
this
.
muc_invite_modal
.
chatroomview
=
this
;
}
this
.
muc_invite_modal
.
show
(
ev
);
api
.
modal
.
show
(
MUCInviteModal
,
{
'
model
'
:
new
Model
(),
'
chatroomview
'
:
this
},
ev
);
},
...
...
@@ -1365,17 +1355,11 @@ export const RoomsPanel = View.extend({
},
showAddRoomModal
(
ev
)
{
if
(
this
.
add_room_modal
===
undefined
)
{
this
.
add_room_modal
=
new
AddMUCModal
({
'
model
'
:
this
.
model
});
}
this
.
add_room_modal
.
show
(
ev
);
api
.
modal
.
show
(
AddMUCModal
,
{
'
model
'
:
this
.
model
},
ev
);
},
showMUCListModal
(
ev
)
{
if
(
this
.
muc_list_modal
===
undefined
)
{
this
.
muc_list_modal
=
new
MUCListModal
({
'
model
'
:
this
.
model
});
}
this
.
muc_list_modal
.
show
(
ev
);
api
.
modal
.
show
(
MUCListModal
,
{
'
model
'
:
this
.
model
},
ev
);
}
});
...
...
src/converse-profile.js
View file @
1a161ad2
...
...
@@ -61,26 +61,17 @@ converse.plugins.add('converse-profile', {
showProfileModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
profile_modal
===
undefined
)
{
this
.
profile_modal
=
new
_converse
.
ProfileModal
({
model
:
this
.
model
});
}
this
.
profile_modal
.
show
(
ev
);
api
.
modal
.
show
(
_converse
.
ProfileModal
,
{
model
:
this
.
model
},
ev
);
},
showStatusChangeModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
status_modal
===
undefined
)
{
this
.
status_modal
=
new
_converse
.
ChatStatusModal
({
model
:
this
.
model
});
}
this
.
status_modal
.
show
(
ev
);
api
.
modal
.
show
(
_converse
.
ChatStatusModal
,
{
model
:
this
.
model
},
ev
);
},
showUserSettingsModal
(
ev
)
{
ev
.
preventDefault
();
if
(
this
.
user_settings_modal
===
undefined
)
{
this
.
user_settings_modal
=
new
UserSettingsModal
({
model
:
this
.
model
,
_converse
});
}
this
.
user_settings_modal
.
show
(
ev
);
api
.
modal
.
show
(
UserSettingsModal
,
{
model
:
this
.
model
,
_converse
},
ev
);
},
logOut
(
ev
)
{
...
...
src/converse-roomslist.js
View file @
1a161ad2
...
...
@@ -109,10 +109,7 @@ converse.plugins.add('converse-roomslist', {
const
jid
=
ev
.
target
.
getAttribute
(
'
data-room-jid
'
);
const
room
=
_converse
.
chatboxes
.
get
(
jid
);
ev
.
preventDefault
();
if
(
room
.
room_details_modal
===
undefined
)
{
room
.
room_details_modal
=
new
RoomDetailsModal
({
'
model
'
:
room
});
}
room
.
room_details_modal
.
show
(
ev
);
api
.
modal
.
show
(
RoomDetailsModal
,
{
'
model
'
:
room
},
ev
);
},
async
openRoom
(
ev
)
{
...
...
@@ -183,4 +180,3 @@ converse.plugins.add('converse-roomslist', {
api
.
listen
.
on
(
'
reconnected
'
,
initRoomsListView
);
}
});
src/converse-rosterview.js
View file @
1a161ad2
...
...
@@ -629,10 +629,7 @@ converse.plugins.add('converse-rosterview', {
},
showAddContactModal
(
ev
)
{
if
(
this
.
add_contact_modal
===
undefined
)
{
this
.
add_contact_modal
=
new
_converse
.
AddContactModal
({
'
model
'
:
new
Model
()});
}
this
.
add_contact_modal
.
show
(
ev
);
api
.
modal
.
show
(
_converse
.
AddContactModal
,
{
'
model
'
:
new
Model
()},
ev
);
},
createRosterFilter
()
{
...
...
src/modals/alert.js
View file @
1a161ad2
...
...
@@ -4,6 +4,7 @@ import { __ } from '../i18n';
const
Alert
=
BootstrapModal
.
extend
({
id
:
'
alert-modal
'
,
initialize
()
{
BootstrapModal
.
prototype
.
initialize
.
apply
(
this
,
arguments
);
...
...
src/modals/base.js
View file @
1a161ad2
...
...
@@ -2,7 +2,7 @@ import bootstrap from "bootstrap.native";
import
log
from
"
@converse/headless/log
"
;
import
tpl_alert_component
from
"
templates/alert.js
"
;
import
{
View
}
from
'
@converse/skeletor/src/view.js
'
;
import
{
_converse
,
converse
}
from
"
@converse/headless/converse-core
"
;
import
{
_converse
,
api
,
converse
}
from
"
@converse/headless/converse-core
"
;
import
{
render
}
from
'
lit-html
'
;
const
{
sizzle
}
=
converse
.
env
;
...
...
@@ -16,9 +16,15 @@ const BaseModal = View.extend({
'
click .nav-item .nav-link
'
:
'
switchTab
'
},
initialize
()
{
initialize
(
options
)
{
if
(
!
this
.
id
)
{
throw
new
Error
(
"
Each modal class must have a unique id attribute
"
);
}
this
.
render
()
// Allow properties to be set via passed in options
Object
.
assign
(
this
,
options
);
this
.
el
.
setAttribute
(
'
tabindex
'
,
'
-1
'
);
this
.
el
.
setAttribute
(
'
role
'
,
'
dialog
'
);
this
.
el
.
setAttribute
(
'
aria-hidden
'
,
'
true
'
);
...
...
@@ -36,7 +42,7 @@ const BaseModal = View.extend({
onHide
()
{
u
.
removeClass
(
'
selected
'
,
this
.
trigger_el
);
!
this
.
persistent
&&
this
.
remove
(
);
!
this
.
persistent
&&
api
.
modal
.
remove
(
this
);
},
insertIntoDOM
()
{
...
...
src/modals/confirm.js
View file @
1a161ad2
...
...
@@ -6,6 +6,7 @@ const u = converse.env.utils;
const
Confirm
=
BootstrapModal
.
extend
({
id
:
'
confirm-modal
'
,
events
:
{
'
submit .confirm
'
:
'
onConfimation
'
},
...
...
src/modals/image.js
View file @
1a161ad2
...
...
@@ -3,6 +3,8 @@ import tpl_image_modal from "./templates/image.js";
export
default
BootstrapModal
.
extend
({
id
:
'
image-modal
'
,
toHTML
()
{
return
tpl_image_modal
({
'
src
'
:
this
.
src
,
...
...
src/modals/message-versions.js
View file @
1a161ad2
...
...
@@ -3,7 +3,7 @@ import tpl_message_versions_modal from "./templates/message-versions.js";
export
default
BootstrapModal
.
extend
({
id
:
"
message-versions-modal
"
,
toHTML
()
{
return
tpl_message_versions_modal
(
this
.
model
.
toJSON
());
}
...
...
src/modals/moderator-tools.js
View file @
1a161ad2
...
...
@@ -12,6 +12,7 @@ let _converse;
export
default
BootstrapModal
.
extend
({
id
:
"
converse-modtools-modal
"
,
persistent
:
true
,
initialize
(
attrs
)
{
...
...
src/modals/user-details.js
View file @
1a161ad2
...
...
@@ -7,7 +7,22 @@ import { _converse, api, converse } from "@converse/headless/converse-core";
const
u
=
converse
.
env
.
utils
;
function
removeContact
(
contact
)
{
contact
.
removeFromRoster
(
()
=>
contact
.
destroy
(),
(
e
)
=>
{
e
&&
log
.
error
(
e
);
api
.
alert
(
'
error
'
,
__
(
'
Error
'
),
[
__
(
'
Sorry, there was an error while trying to remove %1$s as a contact.
'
,
contact
.
getDisplayName
())
]);
}
);
}
const
UserDetailsModal
=
BootstrapModal
.
extend
({
id
:
'
user-details-modal
'
,
persistent
:
true
,
events
:
{
...
...
@@ -74,23 +89,11 @@ const UserDetailsModal = BootstrapModal.extend({
if
(
!
api
.
settings
.
get
(
'
allow_contact_removal
'
))
{
return
;
}
const
result
=
confirm
(
__
(
"
Are you sure you want to remove this contact?
"
));
if
(
result
===
true
)
{
this
.
modal
.
hide
();
// XXX: This is annoying but necessary to get tests to pass.
// The `dismissHandler` in bootstrap.native tries to
// XXX: The `dismissHandler` in bootstrap.native tries to
// reference the remove button after it's been cleared from
// the DOM, so we delay removing the contact to give it time.
setTimeout
(()
=>
{
this
.
model
.
contact
.
removeFromRoster
(
()
=>
this
.
model
.
contact
.
destroy
(),
(
err
)
=>
{
log
.
error
(
err
);
api
.
alert
(
'
error
'
,
__
(
'
Error
'
),
[
__
(
'
Sorry, there was an error while trying to remove %1$s as a contact.
'
,
this
.
model
.
contact
.
getDisplayName
())
]);
}
);
},
1
);
setTimeout
(()
=>
removeContact
(
this
.
model
.
contact
),
1
);
this
.
modal
.
hide
();
}
},
});
...
...
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