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
9d77a4ef
Commit
9d77a4ef
authored
Nov 18, 2018
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes #129 Add support for XEP-0156.
Only XML is supported for now.
parent
54e9c51a
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
335 additions
and
263 deletions
+335
-263
CHANGES.md
CHANGES.md
+7
-0
docs/source/configuration.rst
docs/source/configuration.rst
+18
-2
spec/bookmarks.js
spec/bookmarks.js
+24
-61
spec/login.js
spec/login.js
+2
-2
spec/register.js
spec/register.js
+11
-11
spec/roomslist.js
spec/roomslist.js
+2
-4
spec/smacks.js
spec/smacks.js
+1
-1
src/converse-chatview.js
src/converse-chatview.js
+1
-1
src/converse-controlbox.js
src/converse-controlbox.js
+15
-13
src/converse-dragresize.js
src/converse-dragresize.js
+1
-1
src/converse-minimize.js
src/converse-minimize.js
+2
-5
src/converse-omemo.js
src/converse-omemo.js
+2
-2
src/converse-register.js
src/converse-register.js
+4
-3
src/headless/converse-bosh.js
src/headless/converse-bosh.js
+18
-13
src/headless/converse-chatboxes.js
src/headless/converse-chatboxes.js
+2
-2
src/headless/converse-core.js
src/headless/converse-core.js
+144
-65
src/headless/converse-muc.js
src/headless/converse-muc.js
+1
-1
src/headless/utils/core.js
src/headless/utils/core.js
+9
-0
tests/mock.js
tests/mock.js
+71
-76
No files found.
CHANGES.md
View file @
9d77a4ef
...
...
@@ -2,11 +2,18 @@
## 6.0.0 (Unreleased)
-
#129: Add support for XEP-0156: Disovering Alternative XMPP Connection Methods. Only XML is supported for now.
-
#1691 Fix
`collection.chatbox is undefined`
errors
-
Prevent editing of sent file uploads.
### Breaking changes
-
In order to add support for XEP-0156, the XMPP connection needs to be created
only once we know the JID of the user that's logging in. This means that the
[
connectionInitialized
](
https://conversejs.org/docs/html/api/-_converse.html#event:connectionInitialized
)
event now fires much later than before. Plugins that rely on
`connectionInitialized`
being triggered before the user's JID has been provided will need to be updated.
-
The following API methods now return promises:
*
`_converse.api.chats.get`
*
`_converse.api.chats.create`
...
...
docs/source/configuration.rst
View file @
9d77a4ef
...
...
@@ -639,6 +639,23 @@ The default chat status that the user wil have. If you for example set this to
``'chat'``, then Converse will send out a presence stanza with ``"show"``
set to ``'chat'`` as soon as you've been logged in.
discover_connection_methods
---------------------------
* Default: ``false``
Use `XEP-0156 <https://xmpp.org/extensions/xep-0156.html>`_ to discover whether
the XMPP host for the current user advertises any Websocket or BOSH connection
URLs that can be used.
If this is set to ``false``, then a `websocket_url`_ or `bosh_service_url`_ need to be
set.
Currently only the XML encoded host-meta resource is supported as shown in
`Example 2 under section 3.3 <https://xmpp.org/extensions/xep-0156.html#httpexamples>`_.
domain_placeholder
------------------
...
...
@@ -647,8 +664,6 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form.
emoji_image_path
----------------
...
...
@@ -1624,6 +1639,7 @@ Allows you to show or hide buttons on the chatboxes' toolbars.
.. _`websocket-url`:
websocket_url
-------------
...
...
spec/bookmarks.js
View file @
9d77a4ef
...
...
@@ -404,8 +404,8 @@
it
(
"
can be retrieved from the XMPP server
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
chatBoxesFetched
'
,
'
roomsPanelRendered
'
,
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
null
,
[
'
chatBoxesFetched
'
,
'
roomsPanelRendered
'
,
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
...
...
@@ -421,25 +421,12 @@
* </pubsub>
* </iq>
*/
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
call
.
args
[
0
]
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)
}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
...
...
@@ -469,7 +456,7 @@
expect
(
_converse
.
bookmarks
.
models
.
length
).
toBe
(
0
);
spyOn
(
_converse
.
bookmarks
,
'
onBookmarksReceived
'
).
and
.
callThrough
();
var
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
var
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
@@ -495,7 +482,7 @@
describe
(
"
The rooms panel
"
,
function
()
{
it
(
"
shows a list of bookmarks
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitUntilDiscoConfirmed
(
...
...
@@ -505,31 +492,19 @@
);
test_utils
.
openControlBox
();
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
expect
(
Strophe
.
serialize
(
call
.
args
[
0
])).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
'
</iq>
'
);
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
@@ -583,7 +558,7 @@
it
(
"
remembers the toggle state of the bookmarks list
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
],
{},
async
function
(
done
,
_converse
)
{
test_utils
.
openControlBox
();
...
...
@@ -593,31 +568,19 @@
[
'
http://jabber.org/protocol/pubsub#publish-options
'
]
);
let
IQ_id
;
const
call
=
await
u
.
waitUntil
(()
=>
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
call
=>
{
const
stanza
=
call
.
args
[
0
];
if
(
!
(
stanza
instanceof
Element
)
||
stanza
.
nodeName
!==
'
iq
'
)
{
return
;
}
if
(
sizzle
(
'
items[node="storage:bookmarks"]
'
,
stanza
).
length
)
{
IQ_id
=
stanza
.
getAttribute
(
'
id
'
);
return
true
;
}
}
).
pop
()
);
expect
(
Strophe
.
serialize
(
call
.
args
[
0
])).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
IQ_id
}
" type="get" xmlns="jabber:client">`
+
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
sent_stanza
=
await
u
.
waitUntil
(
()
=>
IQ_stanzas
.
filter
(
s
=>
sizzle
(
'
items[node="storage:bookmarks"]
'
,
s
).
length
).
pop
());
expect
(
Strophe
.
serialize
(
sent_stanza
)).
toBe
(
`<iq from="romeo@montague.lit/orchard" id="
${
sent_stanza
.
getAttribute
(
'
id
'
)}
" type="get" xmlns="jabber:client">`
+
'
<pubsub xmlns="http://jabber.org/protocol/pubsub">
'
+
'
<items node="storage:bookmarks"/>
'
+
'
</pubsub>
'
+
'
</iq>
'
);
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
})
const
stanza
=
$iq
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
result
'
,
'
id
'
:
sent_stanza
.
getAttribute
(
'
id
'
)
})
.
c
(
'
pubsub
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
PUBSUB
})
.
c
(
'
items
'
,
{
'
node
'
:
'
storage:bookmarks
'
})
.
c
(
'
item
'
,
{
'
id
'
:
'
current
'
})
...
...
spec/login.js
View file @
9d77a4ef
...
...
@@ -8,7 +8,7 @@
it
(
"
contains a checkbox to indicate whether the computer is trusted or not
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
false
},
async
function
(
done
,
_converse
)
{
...
...
@@ -42,7 +42,7 @@
it
(
"
checkbox can be set to false by default
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
trusted
:
false
,
allow_registration
:
false
},
...
...
spec/register.js
View file @
9d77a4ef
...
...
@@ -10,7 +10,7 @@
it
(
"
is not available unless allow_registration=true
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
false
},
async
function
(
done
,
_converse
)
{
...
...
@@ -24,7 +24,7 @@
it
(
"
can be opened by clicking on the registration tab
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -45,18 +45,18 @@
it
(
"
allows the user to choose an XMPP provider's domain
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
spyOn
(
Strophe
.
Connection
.
prototype
,
'
connect
'
);
await
u
.
waitUntil
(()
=>
_
.
get
(
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
'
registerpanel
'
));
test_utils
.
openControlBox
();
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
const
registerview
=
cbview
.
registerpanel
;
spyOn
(
registerview
,
'
onProviderChosen
'
).
and
.
callThrough
();
registerview
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
spyOn
(
_converse
.
connection
,
'
connect
'
);
// Open the register panel
cbview
.
el
.
querySelector
(
'
.toggle-register-login
'
).
click
();
...
...
@@ -75,17 +75,18 @@
form
.
querySelector
(
'
input[name=domain]
'
).
value
=
'
conversejs.org
'
;
submit_button
.
click
();
expect
(
registerview
.
onProviderChosen
).
toHaveBeenCalled
();
expect
(
_converse
.
connection
.
connect
).
toHaveBeenCalled
(
);
await
u
.
waitUntil
(()
=>
_converse
.
connection
.
connect
.
calls
.
count
()
);
done
();
}));
it
(
"
will render a registration form as received from the XMPP provider
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
spyOn
(
Strophe
.
Connection
.
prototype
,
'
connect
'
);
await
u
.
waitUntil
(()
=>
_
.
get
(
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
'
registerpanel
'
));
test_utils
.
openControlBox
();
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
...
...
@@ -97,7 +98,6 @@
spyOn
(
registerview
,
'
onRegistrationFields
'
).
and
.
callThrough
();
spyOn
(
registerview
,
'
renderRegistrationForm
'
).
and
.
callThrough
();
registerview
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
spyOn
(
_converse
.
connection
,
'
connect
'
).
and
.
callThrough
();
expect
(
registerview
.
_registering
).
toBeFalsy
();
expect
(
_converse
.
connection
.
connected
).
toBeFalsy
();
...
...
@@ -105,7 +105,7 @@
registerview
.
el
.
querySelector
(
'
input[type=submit]
'
).
click
();
expect
(
registerview
.
onProviderChosen
).
toHaveBeenCalled
();
expect
(
registerview
.
_registering
).
toBeTruthy
();
expect
(
_converse
.
connection
.
connect
).
toHaveBeenCalled
(
);
await
u
.
waitUntil
(()
=>
_converse
.
connection
.
connect
.
calls
.
count
()
);
let
stanza
=
new
Strophe
.
Builder
(
"
stream:features
"
,
{
'
xmlns:stream
'
:
"
http://etherx.jabber.org/streams
"
,
...
...
@@ -137,7 +137,7 @@
it
(
"
will set form_type to legacy and submit it as legacy
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -194,7 +194,7 @@
it
(
"
will set form_type to xform and submit it as xform
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
allow_registration
:
true
},
async
function
(
done
,
_converse
)
{
...
...
@@ -267,7 +267,7 @@
it
(
"
renders the account registration form
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
auto_login
:
false
,
view_mode
:
'
fullscreen
'
,
allow_registration
:
true
},
...
...
spec/roomslist.js
View file @
9d77a4ef
...
...
@@ -53,7 +53,7 @@
it
(
"
uses bookmarks to determine groupchat names
"
,
mock
.
initConverse
(
{
'
connection
'
:
[
'
send
'
]}
,
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
,
'
emojisInitialized
'
],
{
'
view_mode
'
:
'
fullscreen
'
},
async
function
(
done
,
_converse
)
{
...
...
@@ -113,7 +113,7 @@
describe
(
"
A groupchat shown in the groupchats list
"
,
function
()
{
it
(
"
is highlighted if its currently open
"
,
mock
.
initConverse
(
it
(
"
is highlighted if it
'
s currently open
"
,
mock
.
initConverse
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
,
'
emojisInitialized
'
],
{
view_mode
:
'
fullscreen
'
,
allow_bookmarks
:
false
// Makes testing easier, otherwise we have to mock stanza traffic.
...
...
@@ -137,8 +137,6 @@
expect
(
room_els
.
length
).
toBe
(
1
);
item
=
room_els
[
0
];
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
balcony@chat.shakespeare.lit
'
);
const
conv_el
=
document
.
querySelector
(
'
#conversejs
'
);
conv_el
.
parentElement
.
removeChild
(
conv_el
);
done
();
}));
...
...
spec/smacks.js
View file @
9d77a4ef
...
...
@@ -11,7 +11,7 @@
it
(
"
gets enabled with an <enable> stanza and resumed with a <resume> stanza
"
,
mock
.
initConverse
(
null
,
[
'
c
onnectionInitialized
'
,
'
c
hatBoxesInitialized
'
],
null
,
[
'
chatBoxesInitialized
'
],
{
'
auto_login
'
:
false
,
'
enable_smacks
'
:
true
,
'
show_controlbox_by_default
'
:
true
,
...
...
src/converse-chatview.js
View file @
9d77a4ef
...
...
@@ -1124,7 +1124,7 @@ converse.plugins.add('converse-chatview', {
if
(
Backbone
.
history
.
getFragment
()
===
"
converse/chat?jid=
"
+
this
.
model
.
get
(
'
jid
'
))
{
_converse
.
router
.
navigate
(
''
);
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
// Immediately sending the chat state, because the
// model is going to be destroyed afterwards.
this
.
model
.
setChatState
(
_converse
.
INACTIVE
);
...
...
src/converse-controlbox.js
View file @
9d77a4ef
...
...
@@ -154,6 +154,7 @@ converse.plugins.add('converse-controlbox', {
_converse
.
api
.
promises
.
add
(
'
controlBoxInitialized
'
);
const
addControlBox
=
()
=>
_converse
.
chatboxes
.
add
({
'
id
'
:
'
controlbox
'
});
_converse
.
ControlBox
=
_converse
.
ChatBox
.
extend
({
...
...
@@ -220,9 +221,9 @@ converse.plugins.add('converse-controlbox', {
}
else
{
this
.
hide
();
}
if
(
!
_converse
.
connection
.
connected
||
!
_converse
.
connection
.
authenticated
||
_converse
.
connection
.
disconnecting
)
{
const
connection
=
get
(
_converse
,
'
connection
'
,
{});
if
(
!
connection
.
connected
||
!
connection
.
authenticated
||
connection
.
disconnecting
)
{
this
.
renderLoginPanel
();
}
else
if
(
this
.
model
.
get
(
'
connected
'
))
{
this
.
renderControlBoxPane
();
...
...
@@ -296,7 +297,8 @@ converse.plugins.add('converse-controlbox', {
if
(
_converse
.
sticky_controlbox
)
{
return
;
}
if
(
_converse
.
connection
.
connected
&&
!
_converse
.
connection
.
disconnecting
)
{
const
connection
=
get
(
_converse
,
'
connection
'
,
{});
if
(
connection
.
connected
&&
!
connection
.
disconnecting
)
{
this
.
model
.
save
({
'
closed
'
:
true
});
}
else
{
this
.
model
.
trigger
(
'
hide
'
);
...
...
@@ -319,7 +321,8 @@ converse.plugins.add('converse-controlbox', {
}
u
.
addClass
(
'
hidden
'
,
this
.
el
);
_converse
.
api
.
trigger
(
'
chatBoxClosed
'
,
this
);
if
(
!
_converse
.
connection
.
connected
)
{
if
(
!
_converse
.
api
.
connection
.
connected
())
{
_converse
.
controlboxtoggle
.
render
();
}
_converse
.
controlboxtoggle
.
show
(
callback
);
...
...
@@ -464,7 +467,7 @@ converse.plugins.add('converse-controlbox', {
if
([
"
converse/login
"
,
"
converse/register
"
].
includes
(
Backbone
.
history
.
getFragment
()))
{
_converse
.
router
.
navigate
(
''
,
{
'
replace
'
:
true
});
}
_converse
.
connection
.
reset
();
_converse
.
connection
&&
_converse
.
connection
.
reset
();
_converse
.
api
.
user
.
login
(
jid
,
password
);
}
});
...
...
@@ -510,7 +513,7 @@ converse.plugins.add('converse-controlbox', {
// artifacts (i.e. on page load the toggle is shown only to then
// seconds later be hidden in favor of the controlbox).
this
.
el
.
innerHTML
=
tpl_controlbox_toggle
({
'
label_toggle
'
:
_converse
.
connection
.
connected
?
__
(
'
Chat Contacts
'
)
:
__
(
'
Toggle chat
'
)
'
label_toggle
'
:
_converse
.
api
.
connection
.
connected
()
?
__
(
'
Chat Contacts
'
)
:
__
(
'
Toggle chat
'
)
})
return
this
;
},
...
...
@@ -529,7 +532,7 @@ converse.plugins.add('converse-controlbox', {
if
(
!
controlbox
)
{
controlbox
=
addControlBox
();
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
controlbox
.
save
({
'
closed
'
:
false
});
}
else
{
controlbox
.
trigger
(
'
show
'
);
...
...
@@ -540,7 +543,7 @@ converse.plugins.add('converse-controlbox', {
e
.
preventDefault
();
if
(
u
.
isVisible
(
_converse
.
root
.
querySelector
(
"
#controlbox
"
)))
{
const
controlbox
=
_converse
.
chatboxes
.
get
(
'
controlbox
'
);
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
)
{
controlbox
.
save
({
closed
:
true
});
}
else
{
controlbox
.
trigger
(
'
hide
'
);
...
...
@@ -582,10 +585,9 @@ converse.plugins.add('converse-controlbox', {
});
Promise
.
all
([
_converse
.
api
.
waitUntil
(
'
connectionInitialized
'
),
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
)
]).
then
(
addControlBox
).
catch
(
e
=>
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
FATAL
));
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
)
.
then
(
addControlBox
)
.
catch
(
e
=>
_converse
.
log
(
e
,
Strophe
.
LogLevel
.
FATAL
));
_converse
.
api
.
listen
.
on
(
'
chatBoxesFetched
'
,
()
=>
{
const
controlbox
=
_converse
.
chatboxes
.
get
(
'
controlbox
'
)
||
addControlBox
();
...
...
src/converse-dragresize.js
View file @
9d77a4ef
...
...
@@ -351,7 +351,7 @@ converse.plugins.add('converse-dragresize', {
_converse
.
resizing
.
chatbox
.
width
,
_converse
.
resizing
.
chatbox
.
model
.
get
(
'
default_width
'
)
);
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
_converse
.
resizing
.
chatbox
.
model
.
save
({
'
height
'
:
height
});
_converse
.
resizing
.
chatbox
.
model
.
save
({
'
width
'
:
width
});
}
else
{
...
...
src/converse-minimize.js
View file @
9d77a4ef
...
...
@@ -318,7 +318,7 @@ converse.plugins.add('converse-minimize', {
* @param { _converse.ChatBoxView|_converse.ChatRoomView|_converse.ControlBoxView|_converse.HeadlinesBoxView } [newchat]
*/
async
trimChats
(
newchat
)
{
if
(
_converse
.
no_trimming
||
!
_converse
.
connection
.
connected
||
_converse
.
view_mode
!==
'
overlayed
'
)
{
if
(
_converse
.
no_trimming
||
!
_converse
.
api
.
connection
.
connected
()
||
_converse
.
view_mode
!==
'
overlayed
'
)
{
return
;
}
const
shown_chats
=
this
.
getShownChats
();
...
...
@@ -556,10 +556,7 @@ converse.plugins.add('converse-minimize', {
});
/************************ BEGIN Event Handlers ************************/
Promise
.
all
([
_converse
.
api
.
waitUntil
(
'
connectionInitialized
'
),
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
)
]).
then
(()
=>
{
_converse
.
api
.
waitUntil
(
'
chatBoxViewsInitialized
'
).
then
(()
=>
{
_converse
.
minimized_chats
=
new
_converse
.
MinimizedChats
({
model
:
_converse
.
chatboxes
});
...
...
src/converse-omemo.js
View file @
9d77a4ef
...
...
@@ -240,8 +240,8 @@ converse.plugins.add('converse-omemo', {
/* The initialize function gets called as soon as the plugin is
* loaded by Converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
,
{
__
}
=
_converse
;
const
{
_converse
}
=
this
;
const
{
__
}
=
_converse
;
_converse
.
api
.
settings
.
update
({
'
omemo_default
'
:
false
,
...
...
src/converse-register.js
View file @
9d77a4ef
...
...
@@ -175,7 +175,7 @@ converse.plugins.add('converse-register', {
initialize
()
{
this
.
reset
();
this
.
registerHooks
(
);
_converse
.
api
.
listen
.
on
(
'
connectionInitialized
'
,
()
=>
this
.
registerHooks
()
);
},
render
()
{
...
...
@@ -340,7 +340,7 @@ converse.plugins.add('converse-register', {
* @method _converse.RegisterPanel#fetchRegistrationForm
* @param { String } domain_name - XMPP server domain
*/
fetchRegistrationForm
(
domain_name
)
{
async
fetchRegistrationForm
(
domain_name
)
{
if
(
!
this
.
model
.
get
(
'
registration_form_rendered
'
))
{
this
.
renderRegistrationRequest
();
}
...
...
@@ -348,7 +348,8 @@ converse.plugins.add('converse-register', {
'
domain
'
:
Strophe
.
getDomainFromJid
(
domain_name
),
'
_registering
'
:
true
});
_converse
.
connection
.
connect
(
this
.
domain
,
""
,
this
.
onConnectStatusChanged
.
bind
(
this
));
await
_converse
.
initConnection
(
this
.
domain
);
_converse
.
connection
.
connect
(
this
.
domain
,
""
,
status
=>
this
.
onConnectStatusChanged
(
status
));
return
false
;
},
...
...
src/headless/converse-bosh.js
View file @
9d77a4ef
...
...
@@ -19,6 +19,10 @@ const BOSH_SESSION_ID = 'converse.bosh-session';
converse
.
plugins
.
add
(
'
converse-bosh
'
,
{
enabled
()
{
return
true
;
},
initialize
()
{
const
{
_converse
}
=
this
;
...
...
@@ -35,9 +39,15 @@ converse.plugins.add('converse-bosh', {
_converse
.
bosh_session
.
browserStorage
=
new
BrowserStorage
.
session
(
id
);
await
new
Promise
(
resolve
=>
_converse
.
bosh_session
.
fetch
({
'
success
'
:
resolve
,
'
error
'
:
resolve
}));
}
if
(
_converse
.
jid
&&
_converse
.
bosh_session
.
get
(
'
jid
'
)
===
_converse
.
jid
)
{
_converse
.
bosh_session
.
clear
({
'
silent
'
:
true
});
_converse
.
bosh_session
.
save
({
'
jid
'
:
_converse
.
jid
,
id
});
if
(
_converse
.
jid
)
{
if
(
_converse
.
bosh_session
.
get
(
'
jid
'
)
!==
_converse
.
jid
)
{
const
jid
=
await
_converse
.
setUserJID
(
_converse
.
jid
);
_converse
.
bosh_session
.
clear
({
'
silent
'
:
true
});
_converse
.
bosh_session
.
save
({
jid
});
}
}
else
{
// Keepalive
const
jid
=
_converse
.
bosh_session
.
get
(
'
jid
'
);
jid
&&
await
_converse
.
setUserJID
();
}
return
_converse
.
bosh_session
;
}
...
...
@@ -45,17 +55,17 @@ converse.plugins.add('converse-bosh', {
_converse
.
startNewPreboundBOSHSession
=
function
()
{
if
(
!
_converse
.
prebind_url
)
{
throw
new
Error
(
"
attemptPreboundSession: If you use prebind then you MUST supply a prebind_url
"
);
throw
new
Error
(
"
startNewPreboundBOSHSession: If you use prebind then you MUST supply a prebind_url
"
);
}
const
xhr
=
new
XMLHttpRequest
();
xhr
.
open
(
'
GET
'
,
_converse
.
prebind_url
,
true
);
xhr
.
setRequestHeader
(
'
Accept
'
,
'
application/json, text/javascript
'
);
xhr
.
onload
=
function
()
{
xhr
.
onload
=
async
function
()
{
if
(
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
const
data
=
JSON
.
parse
(
xhr
.
responseText
);
const
jid
=
await
_converse
.
setUserJID
(
data
.
jid
);
_converse
.
connection
.
attach
(
data
.
jid
,
jid
,
data
.
sid
,
data
.
rid
,
_converse
.
onConnectStatusChanged
...
...
@@ -79,9 +89,6 @@ converse.plugins.add('converse-bosh', {
_converse
.
restoreBOSHSession
=
async
function
()
{
if
(
!
_converse
.
api
.
connection
.
isType
(
'
bosh
'
))
{
return
false
;
}
const
jid
=
(
await
initBOSHSession
()).
get
(
'
jid
'
);
if
(
jid
)
{
try
{
...
...
@@ -119,9 +126,7 @@ converse.plugins.add('converse-bosh', {
}
});
_converse
.
api
.
listen
.
on
(
'
addClientFeatures
'
,
()
=>
_converse
.
api
.
disco
.
own
.
features
.
add
(
Strophe
.
NS
.
BOSH
)
);
_converse
.
api
.
listen
.
on
(
'
addClientFeatures
'
,
()
=>
_converse
.
api
.
disco
.
own
.
features
.
add
(
Strophe
.
NS
.
BOSH
));
/************************ END Event Handlers ************************/
...
...
src/headless/converse-chatboxes.js
View file @
9d77a4ef
...
...
@@ -850,8 +850,8 @@ converse.plugins.add('converse-chatboxes', {
'
to
'
:
this
.
get
(
'
jid
'
),
'
type
'
:
'
chat
'
}).
c
(
this
.
get
(
'
chat_state
'
),
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
up
()
.
c
(
'
no-store
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
HINTS
}).
up
()
.
c
(
'
no-permanent-store
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
HINTS
})
.
c
(
'
no-store
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
HINTS
}).
up
()
.
c
(
'
no-permanent-store
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
HINTS
})
);
}
},
...
...
src/headless/converse-core.js
View file @
9d77a4ef
This diff is collapsed.
Click to expand it.
src/headless/converse-muc.js
View file @
9d77a4ef
...
...
@@ -633,7 +633,7 @@ converse.plugins.add('converse-muc', {
disco_entity
.
destroy
();
}
}
if
(
_converse
.
connection
.
connected
)
{
if
(
_converse
.
api
.
connection
.
connected
()
)
{
this
.
sendUnavailablePresence
(
exit_msg
);
}
u
.
safeSave
(
this
,
{
'
connection_status
'
:
converse
.
ROOMSTATUS
.
DISCONNECTED
});
...
...
src/headless/utils/core.js
View file @
9d77a4ef
...
...
@@ -107,6 +107,15 @@ u.isSameBareJID = function (jid1, jid2) {
Strophe
.
getBareJidFromJid
(
jid2
).
toLowerCase
();
};
u
.
isSameDomain
=
function
(
jid1
,
jid2
)
{
if
(
!
_
.
isString
(
jid1
)
||
!
_
.
isString
(
jid2
))
{
return
false
;
}
return
Strophe
.
getDomainFromJid
(
jid1
).
toLowerCase
()
===
Strophe
.
getDomainFromJid
(
jid2
).
toLowerCase
();
};
u
.
isNewMessage
=
function
(
message
)
{
/* Given a stanza, determine whether it's a new
* message, i.e. not a MAM archived one.
...
...
tests/mock.js
View file @
9d77a4ef
...
...
@@ -9,7 +9,6 @@
const
Strophe
=
converse
.
env
.
Strophe
;
const
dayjs
=
converse
.
env
.
dayjs
;
const
$iq
=
converse
.
env
.
$iq
;
const
u
=
converse
.
env
.
utils
;
window
.
libsignal
=
{
'
SignalProtocolAddress
'
:
function
(
name
,
device_id
)
{
...
...
@@ -32,7 +31,7 @@
return
Promise
.
resolve
(
key_and_tag
);
}
},
'
SessionBuilder
'
:
function
(
storage
,
remote_address
)
{
'
SessionBuilder
'
:
function
(
storage
,
remote_address
)
{
// eslint-disable-line no-unused-vars
this
.
processPreKey
=
function
()
{
return
Promise
.
resolve
();
}
...
...
@@ -116,95 +115,87 @@
'
preventDefault
'
:
function
()
{}
};
mock
.
mock_connection
=
function
()
{
// eslint-disable-line wrap-iife
return
function
()
{
Strophe
.
Bosh
.
prototype
.
_processRequest
=
function
()
{};
// Don't attempt to send out stanzas
const
c
=
new
Strophe
.
Connection
(
'
jasmine tests
'
);
const
sendIQ
=
c
.
sendIQ
;
c
.
IQ_stanzas
=
[];
c
.
IQ_ids
=
[];
c
.
sendIQ
=
function
(
iq
,
callback
,
errback
)
{
if
(
!
_
.
isElement
(
iq
))
{
iq
=
iq
.
nodeTree
;
}
this
.
IQ_stanzas
.
push
(
iq
);
const
id
=
sendIQ
.
bind
(
this
)(
iq
,
callback
,
errback
);
this
.
IQ_ids
.
push
(
id
);
return
id
;
const
OriginalConnection
=
Strophe
.
Connection
;
function
MockConnection
(
service
,
options
)
{
OriginalConnection
.
call
(
this
,
service
,
options
);
Strophe
.
Bosh
.
prototype
.
_processRequest
=
function
()
{};
// Don't attempt to send out stanzas
const
sendIQ
=
this
.
sendIQ
;
this
.
IQ_stanzas
=
[];
this
.
IQ_ids
=
[];
this
.
sendIQ
=
function
(
iq
,
callback
,
errback
)
{
if
(
!
_
.
isElement
(
iq
))
{
iq
=
iq
.
nodeTree
;
}
this
.
IQ_stanzas
.
push
(
iq
);
const
id
=
sendIQ
.
bind
(
this
)(
iq
,
callback
,
errback
);
this
.
IQ_ids
.
push
(
id
);
return
id
;
}
const
send
=
c
.
send
;
c
.
sent_stanzas
=
[];
c
.
send
=
function
(
stanza
)
{
if
(
_
.
isElement
(
stanza
))
{
this
.
sent_stanzas
.
push
(
stanza
);
}
else
{
this
.
sent_stanzas
.
push
(
stanza
.
nodeTree
);
}
return
send
.
apply
(
this
,
arguments
);
const
send
=
this
.
send
;
this
.
sent_stanzas
=
[];
this
.
send
=
function
(
stanza
)
{
if
(
_
.
isElement
(
stanza
))
{
this
.
sent_stanzas
.
push
(
stanza
);
}
else
{
this
.
sent_stanzas
.
push
(
stanza
.
nodeTree
);
}
return
send
.
apply
(
this
,
arguments
);
}
c
.
features
=
Strophe
.
xmlHtmlNode
(
'
<stream:features xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
'
+
'
<ver xmlns="urn:xmpp:features:rosterver"/>
'
+
'
<csi xmlns="urn:xmpp:csi:0"/>
'
+
'
<c
xmlns="http://jabber.org/protocol/caps" ver="UwBpfJpEt3IoLYfWma/o/p3FFRo=" hash="sha-1" node="http://prosody.im"/>
'
+
'
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
'
+
'
<required/>
'
+
'
</bind>
'
+
`<sm xmlns='urn:xmpp:sm:3'/>`
+
'
<session xmlns="urn:ietf:params:xml:ns:xmpp-session">
'
+
'
<optional/>
'
+
'
</session>
'
+
'
</stream:features>
'
).
firstChild
;
this
.
features
=
Strophe
.
xmlHtmlNode
(
'
<stream:features xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
'
+
'
<ver xmlns="urn:xmpp:features:rosterver"/>
'
+
'
<csi xmlns="urn:xmpp:csi:0"/>
'
+
'
<this
xmlns="http://jabber.org/protocol/caps" ver="UwBpfJpEt3IoLYfWma/o/p3FFRo=" hash="sha-1" node="http://prosody.im"/>
'
+
'
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
'
+
'
<required/>
'
+
'
</bind>
'
+
`<sm xmlns='urn:xmpp:sm:3'/>`
+
'
<session xmlns="urn:ietf:params:xml:ns:xmpp-session">
'
+
'
<optional/>
'
+
'
</session>
'
+
'
</stream:features>
'
).
firstChild
;
c
.
_proto
.
_connect
=
function
()
{
c
.
connected
=
true
;
c
.
mock
=
true
;
c
.
jid
=
'
romeo@montague.lit/orchard
'
;
c
.
_changeConnectStatus
(
Strophe
.
Status
.
BINDREQUIRED
);
};
this
.
_proto
.
_connect
=
()
=>
{
this
.
connected
=
true
;
this
.
mock
=
true
;
this
.
jid
=
'
romeo@montague.lit/orchard
'
;
this
.
_changeConnectStatus
(
Strophe
.
Status
.
BINDREQUIRED
);
};
c
.
bind
=
function
()
{
c
.
authenticated
=
true
;
this
.
authenticated
=
true
;
c
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
};
this
.
bind
=
()
=>
{
this
.
authenticated
=
true
;
this
.
authenticated
=
true
;
this
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
};
c
.
_proto
.
_disconnect
=
function
()
{
c
.
_onDisconnectTimeout
()
;
}
this
.
_proto
.
_disconnect
=
()
=>
this
.
_onDisconnectTimeout
();
this
.
_proto
.
_onDisconnectTimeout
=
_
.
noop
;
}
c
.
_proto
.
_onDisconnectTimeout
=
_
.
noop
;
return
c
;
};
}();
MockConnection
.
prototype
=
Object
.
create
(
OriginalConnection
.
prototype
);
Strophe
.
Connection
=
MockConnection
;
async
function
initConverse
(
settings
,
spies
=
{},
promises
)
{
async
function
initConverse
(
settings
,
spies
=
{})
{
window
.
localStorage
.
clear
();
window
.
sessionStorage
.
clear
();
const
el
=
document
.
querySelector
(
'
#conversejs
'
);
if
(
el
)
{
el
.
parentElement
.
removeChild
(
el
);
}
const
connection
=
mock
.
mock_connection
();
if
(
spies
&&
spies
.
connection
)
{
spies
.
connection
.
forEach
(
method
=>
spyOn
(
connection
,
method
));
}
const
_converse
=
await
converse
.
initialize
(
Object
.
assign
({
'
i18n
'
:
'
en
'
,
'
animate
'
:
false
,
'
auto_subscribe
'
:
false
,
'
play_sounds
'
:
false
,
'
bosh_service_url
'
:
'
montague.lit/http-bind
'
,
'
connection
'
:
connection
,
'
animate
'
:
false
,
'
use_emojione
'
:
false
,
'
debug
'
:
false
,
'
i18n
'
:
'
en
'
,
'
no_trimming
'
:
true
,
'
play_sounds
'
:
false
,
'
use_emojione
'
:
false
,
'
view_mode
'
:
mock
.
view_mode
,
'
debug
'
:
false
},
settings
||
{}));
if
(
spies
&&
spies
.
_converse
)
{
...
...
@@ -214,7 +205,7 @@
_converse
.
ChatBoxViews
.
prototype
.
trimChat
=
function
()
{};
_converse
.
api
.
vcard
.
get
=
function
(
model
,
force
)
{
return
new
Promise
(
(
resolve
,
reject
)
=>
{
return
new
Promise
(
resolve
=>
{
let
jid
;
if
(
_
.
isString
(
model
))
{
jid
=
model
;
...
...
@@ -263,9 +254,13 @@
return
async
done
=>
{
const
_converse
=
await
initConverse
(
settings
,
spies
);
async
function
_done
()
{
await
_converse
.
api
.
user
.
logout
();
if
(
_converse
.
api
.
connection
.
connected
())
{
await
_converse
.
api
.
user
.
logout
();
}
const
el
=
document
.
querySelector
(
'
#conversejs
'
);
el
.
parentElement
.
removeChild
(
el
);
if
(
el
)
{
el
.
parentElement
.
removeChild
(
el
);
}
done
();
}
await
Promise
.
all
((
promise_names
||
[]).
map
(
_converse
.
api
.
waitUntil
));
...
...
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