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
7660dbfb
Commit
7660dbfb
authored
Apr 12, 2018
by
worlword
Browse files
Options
Browse Files
Download
Plain Diff
merge httpFileUpload-Branch with master
parents
2ec0dd75
c9a9d011
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
479 additions
and
17 deletions
+479
-17
CHANGES.md
CHANGES.md
+7
-0
locale/de/LC_MESSAGES/converse.po
locale/de/LC_MESSAGES/converse.po
+4
-0
spec/chatbox.js
spec/chatbox.js
+1
-1
spec/headline.js
spec/headline.js
+1
-1
spec/http-file-upload.js
spec/http-file-upload.js
+206
-0
src/build.js
src/build.js
+1
-0
src/config.js
src/config.js
+1
-0
src/converse-chatboxes.js
src/converse-chatboxes.js
+115
-3
src/converse-chatview.js
src/converse-chatview.js
+30
-11
src/converse-core.js
src/converse-core.js
+1
-0
src/converse-http-file-upload.js
src/converse-http-file-upload.js
+79
-0
src/converse-muc-views.js
src/converse-muc-views.js
+6
-1
src/converse-muc.js
src/converse-muc.js
+12
-0
src/converse.js
src/converse.js
+1
-0
src/inverse.js
src/inverse.js
+1
-0
src/templates/toolbar_fileupload.html
src/templates/toolbar_fileupload.html
+4
-0
src/utils/core.js
src/utils/core.js
+8
-0
tests/runner-transpiled.js
tests/runner-transpiled.js
+1
-0
No files found.
CHANGES.md
View file @
7660dbfb
# Changelog
## Http-File-Upload
## New Features
-
files can now be send via http-file-upload (XEP-0363)
-
mp4 and mp3 files will now be playable directly in chat.
## 4.0.0 (Unreleased)
## UI changes
...
...
locale/de/LC_MESSAGES/converse.po
View file @
7660dbfb
...
...
@@ -145,6 +145,10 @@ msgstr "tippt nicht mehr"
msgid "has gone away"
msgstr "ist jetzt abwesend"
#: src/converse-chatview.js:860
msgid "Choose a file to send"
msgstr "Datei versenden"
#: dist/converse-no-dependencies.js:14851
#: dist/converse-no-dependencies.js:23427
msgid "Remove messages"
...
...
spec/chatbox.js
View file @
7660dbfb
...
...
@@ -416,7 +416,7 @@
expect
(
view
).
toBeDefined
();
var
$toolbar
=
$
(
view
.
el
).
find
(
'
ul.chat-toolbar
'
);
expect
(
$toolbar
.
length
).
toBe
(
1
);
expect
(
$toolbar
.
children
(
'
li
'
).
length
).
toBe
(
2
);
expect
(
$toolbar
.
children
(
'
li
'
).
length
).
toBe
(
3
);
done
();
}));
...
...
spec/headline.js
View file @
7660dbfb
...
...
@@ -42,7 +42,7 @@
it
(
"
will open and display headline messages
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
/* <message from='notify.example.com'
* to='romeo@im.example.com'
* type='headline'
...
...
spec/http-file-upload.js
0 → 100644
View file @
7660dbfb
(
function
(
root
,
factory
)
{
define
([
"
jasmine
"
,
"
jquery
"
,
"
converse-core
"
,
"
mock
"
,
"
test-utils
"
],
factory
);
}
(
this
,
function
(
jasmine
,
$
,
converse
,
mock
,
test_utils
)
{
"
use strict
"
;
var
Strophe
=
converse
.
env
.
Strophe
;
var
$iq
=
converse
.
env
.
$iq
;
var
_
=
converse
.
env
.
_
;
var
f
=
converse
.
env
.
f
;
describe
(
"
XEP-0363: HTTP File Upload
"
,
function
()
{
describe
(
"
Discovering support
"
,
function
()
{
it
(
"
is done automatically
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
var
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
var
IQ_ids
=
_converse
.
connection
.
IQ_ids
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[],
[]).
then
(
function
()
{
test_utils
.
waitUntil
(
function
()
{
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
}).
length
>
0
;
},
300
).
then
(
function
()
{
/* <iq type='result'
* from='plays.shakespeare.lit'
* to='romeo@montague.net/orchard'
* id='info1'>
* <query xmlns='http://jabber.org/protocol/disco#info'>
* <identity
* category='server'
* type='im'/>
* <feature var='http://jabber.org/protocol/disco#info'/>
* <feature var='http://jabber.org/protocol/disco#items'/>
* </query>
* </iq>
*/
var
stanza
=
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
})[
0
];
var
info_IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
from
'
:
'
localhost
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
info_IQ_id
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
server
'
,
'
type
'
:
'
im
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#info
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#items
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
localhost
'
)).
toBe
(
true
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
dummy@localhost
'
)).
toBe
(
true
);
expect
(
entities
.
get
(
_converse
.
domain
).
features
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
_converse
.
domain
).
identities
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#items feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]
'
);
}).
length
>
0
;
},
300
);
});
}).
then
(
function
()
{
/* <iq from='montague.tld'
* id='step_01'
* to='romeo@montague.tld/garden'
* type='result'>
* <query xmlns='http://jabber.org/protocol/disco#items'>
* <item jid='upload.montague.tld' name='HTTP File Upload' />
* <item jid='conference.montague.tld' name='Chatroom Service' />
* </query>
* </iq>
*/
var
stanza
=
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]
'
);
})[
0
];
var
items_IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
from
'
:
'
localhost
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
items_IQ_id
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#items
'
})
.
c
(
'
item
'
,
{
'
jid
'
:
'
upload.localhost
'
,
'
name
'
:
'
HTTP File Upload
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
'
localhost
'
).
items
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#info feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
}).
length
>
0
;
},
300
);
});
}).
then
(
function
()
{
var
stanza
=
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
})[
0
];
var
IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
expect
(
stanza
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource' to='upload.localhost' type='get' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
"
<query xmlns='http://jabber.org/protocol/disco#info'/>
"
+
"
</iq>
"
);
// Upload service responds and reports a maximum file size of 5MiB
/* <iq from='upload.montague.tld'
* id='step_02'
* to='romeo@montague.tld/garden'
* type='result'>
* <query xmlns='http://jabber.org/protocol/disco#info'>
* <identity category='store'
* type='file'
* name='HTTP File Upload' />
* <feature var='urn:xmpp:http:upload:0' />
* <x type='result' xmlns='jabber:x:data'>
* <field var='FORM_TYPE' type='hidden'>
* <value>urn:xmpp:http:upload:0</value>
* </field>
* <field var='max-file-size'>
* <value>5242880</value>
* </field>
* </x>
* </query>
* </iq>
*/
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
IQ_id
,
'
from
'
:
'
upload.localhost
'
})
.
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
store
'
,
'
type
'
:
'
file
'
,
'
name
'
:
'
HTTP File Upload
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
urn:xmpp:http:upload:0
'
}).
up
()
.
c
(
'
x
'
,
{
'
type
'
:
'
result
'
,
'
xmlns
'
:
'
jabber:x:data
'
})
.
c
(
'
field
'
,
{
'
var
'
:
'
FORM_TYPE
'
,
'
type
'
:
'
hidden
'
})
.
c
(
'
value
'
).
t
(
'
urn:xmpp:http:upload:0
'
).
up
().
up
()
.
c
(
'
field
'
,
{
'
var
'
:
'
max-file-size
'
})
.
c
(
'
value
'
).
t
(
'
5242880
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
get
(
'
localhost
'
).
items
.
get
(
'
upload.localhost
'
).
identities
.
where
({
'
category
'
:
'
store
'
}).
length
).
toBe
(
1
);
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
_converse
.
domain
).
then
(
function
(
result
)
{
console
.
log
(
"
in the test the service is supported
"
);
expect
(
result
.
length
).
toBe
(
1
);
expect
(
result
[
0
].
get
(
'
jid
'
)).
toBe
(
'
upload.localhost
'
);
done
();
}
);
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
));
})
})
}));
});
describe
(
"
When supported
"
,
function
()
{
describe
(
"
A file upload toolbar button
"
,
function
()
{
it
(
"
appears in private chats
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[{
'
category
'
:
'
server
'
,
'
type
'
:
'
IM
'
}],
[
'
http://jabber.org/protocol/disco#items
'
],
[],
'
info
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.localhost
'
],
'
items
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.localhost
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]).
then
(
function
()
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
test_utils
.
waitUntil
(
function
()
{
return
view
.
el
.
querySelector
(
'
.upload-file
'
);
},
150
).
then
(
function
()
{
expect
(
view
.
el
.
querySelector
(
'
.chat-toolbar .upload-file
'
)).
not
.
toBe
(
null
);
done
();
});
});
});
});
}));
it
(
"
appears in MUC chats
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
done
();
}));
});
});
});
}));
src/build.js
View file @
7660dbfb
...
...
@@ -13,6 +13,7 @@
"
converse-dragresize
"
:
"
builds/converse-dragresize
"
,
"
converse-fullscreen
"
:
"
builds/converse-fullscreen
"
,
"
converse-headline
"
:
"
builds/converse-headline
"
,
"
converse-http-file-upload
"
:
"
builds/converse-http-file-upload
"
,
"
converse-mam
"
:
"
builds/converse-mam
"
,
"
converse-minimize
"
:
"
builds/converse-minimize
"
,
"
converse-modal
"
:
"
builds/converse-modal
"
,
...
...
src/config.js
View file @
7660dbfb
...
...
@@ -74,6 +74,7 @@ require.config({
"
converse-dragresize
"
:
"
src/converse-dragresize
"
,
"
converse-fullscreen
"
:
"
src/converse-fullscreen
"
,
"
converse-headline
"
:
"
src/converse-headline
"
,
"
converse-http-file-upload
"
:
"
src/converse-http-file-upload
"
,
"
converse-mam
"
:
"
src/converse-mam
"
,
"
converse-minimize
"
:
"
src/converse-minimize
"
,
"
converse-modal
"
:
"
src/converse-modal
"
,
...
...
src/converse-chatboxes.js
View file @
7660dbfb
...
...
@@ -15,8 +15,8 @@
}(
this
,
function
(
converse
,
tpl_chatboxes
)
{
"
use strict
"
;
const
{
Backbone
,
Promise
,
Strophe
,
b64_sha1
,
moment
,
utils
,
_
}
=
converse
.
env
;
const
{
$msg
,
Backbone
,
Promise
,
Strophe
,
b64_sha1
,
moment
,
utils
,
_
}
=
converse
.
env
;
Strophe
.
addNamespace
(
'
OUTOFBAND
'
,
'
jabber:x:oob
'
);
converse
.
plugins
.
add
(
'
converse-chatboxes
'
,
{
...
...
@@ -50,7 +50,8 @@
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
;
const
{
_converse
}
=
this
,
{
__
}
=
_converse
;
_converse
.
api
.
promises
.
add
([
'
chatBoxesFetched
'
,
...
...
@@ -115,6 +116,117 @@
});
},
createFileMessageStanza
(
message
,
to
){
const
stanza
=
$msg
({
'
from
'
:
_converse
.
connection
.
jid
,
'
to
'
:
to
,
'
type
'
:
'
chat
'
,
'
id
'
:
message
.
get
(
'
msgid
'
)
}).
c
(
'
body
'
).
t
(
message
.
get
(
'
message
'
)).
up
()
.
c
(
_converse
.
ACTIVE
,
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
up
()
.
c
(
'
x
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
OUTOFBAND
}).
c
(
'
url
'
).
t
(
message
.
get
(
'
message
'
)).
up
();
return
stanza
;
},
sendFile
(
file
,
chatbox
)
{
const
self
=
this
;
console
.
log
(
'
Send file via http upload
'
);
const
request_slot_url
=
'
upload.
'
+
_converse
.
domain
;
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
request_slot_url
)
.
then
((
result
)
=>
{
chatbox
.
showHelpMessages
([
__
(
'
The file upload starts now
'
)],
'
info
'
);
self
.
requestSlot
(
file
,
request_slot_url
,
function
(
data
)
{
if
(
!
data
)
{
// general error
console
.
log
(
'
Unknown error while requesting upload slot.
'
);
alert
(
__
(
'
File upload failed. Please check the log.
'
));
}
else
if
(
data
.
error
)
{
// specific error
console
.
log
(
'
The XMPP-Server return an error of the type:
'
+
data
.
error
.
type
);
alert
(
__
(
'
File upload failed. Please check the log.
'
));
}
else
if
(
data
.
get
&&
data
.
put
)
{
console
.
log
(
'
slot received, start upload to
'
+
data
.
put
);
self
.
uploadFile
(
data
.
put
,
file
,
function
()
{
console
.
log
(
data
.
put
);
chatbox
.
onMessageSubmitted
(
data
.
put
,
null
,
file
);
});
}
});
});
},
requestSlot
(
file
,
request_slot_url
,
cb
)
{
const
self
=
this
;
console
.
log
(
"
try sending file to:
"
+
request_slot_url
);
const
iq
=
converse
.
env
.
$iq
({
to
:
request_slot_url
,
type
:
'
get
'
}).
c
(
'
request
'
,
{
xmlns
:
Strophe
.
NS
.
HTTPUPLOAD
}).
c
(
'
filename
'
).
t
(
file
.
name
)
.
up
()
.
c
(
'
size
'
).
t
(
file
.
size
);
_converse
.
connection
.
sendIQ
(
iq
,
function
(
stanza
)
{
self
.
successfulRequestSlotCB
(
stanza
,
cb
);
},
function
(
stanza
)
{
self
.
failedRequestSlotCB
(
stanza
,
cb
);
});
},
uploadFile
(
url
,
file
,
success_cb
)
{
console
.
log
(
"
uploadFile start
"
);
const
xmlhttp
=
new
XMLHttpRequest
();
const
contentType
=
'
application/octet-stream
'
;
xmlhttp
.
onreadystatechange
=
function
()
{
if
(
xmlhttp
.
readyState
===
XMLHttpRequest
.
DONE
)
{
console
.
log
(
"
Status:
"
+
xmlhttp
.
status
);
if
(
xmlhttp
.
status
===
200
||
xmlhttp
.
status
===
201
)
{
console
.
log
(
'
file successful uploaded
'
);
if
(
success_cb
)
{
success_cb
();
}
}
else
{
console
.
log
(
'
error while uploading file to
'
+
url
);
alert
(
__
(
'
Could not upload File please try again.
'
));
}
}
};
xmlhttp
.
open
(
'
PUT
'
,
url
,
true
);
xmlhttp
.
setRequestHeader
(
"
Content-type
"
,
contentType
);
xmlhttp
.
send
(
file
);
console
.
log
(
"
uploadFile end
"
);
},
/**
* Process successful response to slot request.
*/
successfulRequestSlotCB
(
stanza
,
cb
)
{
const
slot
=
stanza
.
getElementsByTagName
(
'
slot
'
)[
0
];
if
(
slot
!=
undefined
)
{
var
put
=
slot
.
getElementsByTagName
(
'
put
'
)[
0
].
textContent
;
var
get
=
slot
.
getElementsByTagName
(
'
get
'
)[
0
].
textContent
;
cb
({
put
:
put
,
get
:
get
});
}
else
{
this
.
failedRequestSlotCB
(
stanza
,
cb
);
}
},
/**
* Process failed response to slot request.
*/
failedRequestSlotCB
(
stanza
,
cb
)
{
alert
(
__
(
'
Could not upload File please try again.
'
));
},
getMessageBody
(
message
)
{
const
type
=
message
.
getAttribute
(
'
type
'
);
return
(
type
===
'
error
'
)
?
...
...
src/converse-chatview.js
View file @
7660dbfb
...
...
@@ -28,6 +28,7 @@
"
tpl!spoiler_message
"
,
"
tpl!status_message
"
,
"
tpl!toolbar
"
,
"
converse-http-file-upload
"
,
"
converse-chatboxes
"
],
factory
);
}(
this
,
function
(
...
...
@@ -50,7 +51,8 @@
tpl_spoiler_button
,
tpl_spoiler_message
,
tpl_status_message
,
tpl_toolbar
tpl_toolbar
,
filetransfer
)
{
"
use strict
"
;
const
{
$msg
,
Backbone
,
Promise
,
Strophe
,
_
,
b64_sha1
,
f
,
sizzle
,
moment
}
=
converse
.
env
;
...
...
@@ -114,7 +116,8 @@
'
call
'
:
false
,
'
clear
'
:
true
,
'
emoji
'
:
true
,
'
spoiler
'
:
true
'
spoiler
'
:
true
,
'
fileUpload
'
:
true
},
});
emojione
.
imagePathPNG
=
_converse
.
emojione_image_path
;
...
...
@@ -237,7 +240,6 @@
}
});
_converse
.
ChatBoxView
=
Backbone
.
NativeView
.
extend
({
length
:
200
,
className
:
'
chatbox hidden
'
,
...
...
@@ -253,7 +255,7 @@
'
click .toggle-smiley
'
:
'
toggleEmojiMenu
'
,
'
click .toggle-spoiler
'
:
'
toggleSpoilerMessage
'
,
'
click .toggle-compose-spoiler
'
:
'
toggleComposeSpoilerMessage
'
,
'
keypress .chat-textarea
'
:
'
keyPressed
'
'
keypress .chat-textarea
'
:
'
keyPressed
'
,
},
initialize
()
{
...
...
@@ -377,6 +379,7 @@
'
label_toggle_spoiler
'
:
label_toggle_spoiler
,
'
show_call_button
'
:
_converse
.
visible_toolbar_buttons
.
call
,
'
show_spoiler_button
'
:
_converse
.
visible_toolbar_buttons
.
spoiler
,
'
show_fileUpload_button
'
:
_converse
.
visible_toolbar_buttons
.
fileUpload
,
'
use_emoji
'
:
_converse
.
visible_toolbar_buttons
.
emoji
,
});
},
...
...
@@ -649,7 +652,14 @@
if
(
attrs
.
is_spoiler
)
{
this
.
renderSpoilerMessage
(
msg
,
attrs
)
}
u
.
renderImageURLs
(
msg_content
).
then
(
this
.
scrollDown
.
bind
(
this
));
if
(
msg_content
.
textContent
.
endsWith
(
'
mp4
'
))
{
msg_content
.
innerHTML
=
u
.
renderMovieURLs
(
msg_content
);
}
else
if
(
msg_content
.
textContent
.
endsWith
(
'
mp3
'
))
{
msg_content
.
innerHTML
=
u
.
renderAudioURLs
(
msg_content
);
}
else
{
u
.
renderImageURLs
(
msg_content
).
then
(
this
.
scrollDown
.
bind
(
this
));
}
return
msg
;
},
...
...
@@ -808,7 +818,9 @@
return
stanza
;
},
sendMessage
(
message
)
{
sendMessage
(
message
,
file
=
null
)
{
/* Responsible for sending off a text message.
*
* Parameters:
...
...
@@ -816,7 +828,13 @@
*/
// TODO: We might want to send to specfic resources.
// Especially in the OTR case.
const
messageStanza
=
this
.
createMessageStanza
(
message
);
var
messageStanza
;
if
(
file
!==
null
){
messageStanza
=
this
.
createFileMessageStanza
(
message
,
this
.
model
.
get
(
'
jid
'
));
}
else
{
messageStanza
=
this
.
createMessageStanza
(
message
);
}
_converse
.
connection
.
send
(
messageStanza
);
if
(
_converse
.
forward_messages
)
{
// Forward the message, so that other connected resources are also aware of it.
...
...
@@ -827,7 +845,7 @@
'
xmns
'
:
Strophe
.
NS
.
DELAY
,
'
stamp
'
:
moment
().
format
()
}).
up
()
.
cnode
(
message
Stanza
.
tree
())
.
cnode
(
message
.
tree
())
);
}
},
...
...
@@ -851,7 +869,7 @@
}
},
onMessageSubmitted
(
text
,
spoiler_hint
)
{
onMessageSubmitted
(
text
,
spoiler_hint
,
file
=
null
)
{
/* This method gets called once the user has typed a message
* and then pressed enter in a chat box.
*
...
...
@@ -870,9 +888,10 @@
if
(
this
.
parseMessageForCommands
(
text
))
{
return
;
}
const
attrs
=
this
.
getOutgoingMessageAttributes
(
text
,
spoiler_hint
)
const
attrs
=
this
.
getOutgoingMessageAttributes
(
text
,
spoiler_hint
)
;
const
message
=
this
.
model
.
messages
.
create
(
attrs
);
this
.
sendMessage
(
message
);
this
.
sendMessage
(
message
,
file
);
},
getOutgoingMessageAttributes
(
text
,
spoiler_hint
)
{
...
...
src/converse-core.js
View file @
7660dbfb
...
...
@@ -78,6 +78,7 @@
'
converse-dropdown
'
,
'
converse-fullscreen
'
,
'
converse-headline
'
,
'
converse-http-file-upload
'
,
'
converse-mam
'
,
'
converse-minimize
'
,
'
converse-modal
'
,
...
...
src/converse-http-file-upload.js
0 → 100644
View file @
7660dbfb
/**
* Adds Support for Http File Upload (XEP-0363)
*
* @see {@link http://xmpp.org/extensions/xep-0363.html}
*/
(
function
(
root
,
factory
)
{
define
([
"
converse-core
"
,
"
tpl!toolbar_fileupload
"
],
factory
);
}(
this
,
function
(
converse
,
tpl_toolbar_fileupload
)
{
"
use strict
"
;
const
{
$msg
,
Backbone
,
Strophe
,
_
,
b64_sha1
,
moment
,
utils
}
=
converse
.
env
;
Strophe
.
addNamespace
(
'
HTTPUPLOAD
'
,
'
urn:xmpp:http:upload
'
);
converse
.
plugins
.
add
(
'
converse-http-file-upload
'
,
{
dependencies
:
[
"
converse-chatboxes
"
,
"
converse-chatview
"
,
"
converse-muc-views
"
],
overrides
:
{
ChatBoxView
:
{
events
:
{
'
click .toggle-fileUpload
'
:
'
toggleFileUpload
'
,
'
change .fileUpload_input
'
:
'
handleFileSelect
'
},
addFileUploadButton
(
options
)
{
const
{
__
}
=
this
.
__super__
.
_converse
;
this
.
el
.
querySelector
(
'
.chat-toolbar
'
).
insertAdjacentHTML
(
'
beforeend
'
,
tpl_toolbar_fileupload
({
'
label_upload_file
'
:
__
(
'
Choose a file to send
'
)}));
},
renderToolbar
(
toolbar
,
options
)
{
const
{
_converse
}
=
this
.
__super__
;
const
result
=
this
.
__super__
.
renderToolbar
.
apply
(
this
,
arguments
);
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
'
upload.
'
+
_converse
.
domain
)
.
then
((
result
)
=>
{
if
(
result
.
supported
)
{
this
.
addFileUploadButton
();
}
});
return
result
;
},
toggleFileUpload
(
ev
)
{
this
.
el
.
querySelector
(
'
.fileUpload_input
'
).
click
();
},
handleFileSelect
(
evt
)
{
var
files
=
evt
.
target
.
files
;
var
file
=
files
[
0
];
this
.
model
.
sendFile
(
file
,
this
);
}
},
ChatRoomView
:
{
events
:
{
'
click .toggle-fileUpload
'
:
'
toggleFileUpload
'
,
'
change .fileUpload_input
'
:
'
handleFileSelect
'
,
}
}
},
initialize
()
{
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const
{
_converse
}
=
this
,
{
__
}
=
_converse
;
}
});
return
converse
;
}));
src/converse-muc-views.js
View file @
7660dbfb
...
...
@@ -826,13 +826,18 @@
this
.
showErrorMessage
(
__
(
"
Error: could not execute the command
"
),
true
);
},
onMessageSubmitted
(
text
)
{
// the notNeeded-Parameter is there so this method has the same amount of parameters as converse-chatview.js->onMessageSubmitted
// this allows to call the same method from diffrent plugins
onMessageSubmitted
(
text
,
notNeeded
=
null
,
file
=
null
)
{
/* Gets called when the user presses enter to send off a
* message in a chat room.
*
* Parameters:
* (String) text - The message text.
*/
if
(
file
!==
null
){
return
this
.
model
.
sendChatRoomFile
(
text
,
this
.
model
.
get
(
'
jid
'
));
}
if
(
_converse
.
muc_disable_moderator_commands
)
{
return
this
.
sendChatRoomMessage
(
text
);
}
...
...
src/converse-muc.js
View file @
7660dbfb
...
...
@@ -335,6 +335,18 @@
const
jid
=
Strophe
.
getBareJidFromJid
(
room
);
return
jid
+
(
nick
!==
null
?
`/
${
nick
}
`
:
""
);
},
sendChatRoomFile
(
text
,
to
)
{
const
msgid
=
_converse
.
connection
.
getUniqueId
();
const
stanza
=
$msg
({
'
from
'
:
_converse
.
connection
.
jid
,
'
to
'
:
to
,
'
type
'
:
'
groupchat
'
,
'
id
'
:
msgid
}).
c
(
"
body
"
).
t
(
text
).
up
()
.
c
(
"
x
"
,
{
'
xmlns
'
:
Strophe
.
NS
.
OUTOFBAND
}).
c
(
'
url
'
).
t
(
text
).
up
();
_converse
.
connection
.
send
(
stanza
);
},
directInvite
(
recipient
,
reason
)
{
/* Send a direct invitation as per XEP-0249
...
...
src/converse.js
View file @
7660dbfb
...
...
@@ -24,6 +24,7 @@ if (typeof define !== 'undefined') {
"
converse-minimize
"
,
// Allows chat boxes to be minimized
"
converse-dragresize
"
,
// Allows chat boxes to be resized by dragging them
"
converse-headline
"
,
// Support for headline messages
"
converse-http-file-upload
"
,
// Support for XEP-0363
"
converse-fullscreen
"
/* END: Removable components */
],
function
(
converse
)
{
...
...
src/inverse.js
View file @
7660dbfb
...
...
@@ -25,6 +25,7 @@ if (typeof define !== 'undefined') {
"
converse-register
"
,
// XEP-0077 In-band registration
"
converse-roomslist
"
,
// Show currently open chat rooms
"
converse-vcard
"
,
// XEP-0054 VCard-temp
"
converse-http-file-upload
"
,
// Support for XEP-0363
/* END: Removable components */
"
converse-inverse
"
,
// Inverse plugin for converse.js
...
...
src/templates/toolbar_fileupload.html
0 → 100644
View file @
7660dbfb
<input
type=
"file"
class=
"fileUpload_input"
style=
"display:none"
/>
<li
class=
"toggle-fileUpload"
>
<a
class=
"fa fa-paperclip"
title=
"{{{o.label_upload_file}}}"
></a>
</li>
\ No newline at end of file
src/utils/core.js
View file @
7660dbfb
...
...
@@ -213,6 +213,14 @@
))
};
u
.
renderMovieURLs
=
function
(
obj
)
{
return
"
<video controls><source src=
\"
"
+
obj
.
textContent
+
"
\"
type=
\"
video/mp4
\"
></video>
"
;
};
u
.
renderAudioURLs
=
function
(
obj
)
{
return
"
<audio controls><source src=
\"
"
+
obj
.
textContent
+
"
\"
type=
\"
audio/mpeg
\"
></audio>
"
;
};
u
.
slideInAllElements
=
function
(
elements
,
duration
=
300
)
{
return
Promise
.
all
(
_
.
map
(
...
...
tests/runner-transpiled.js
View file @
7660dbfb
...
...
@@ -24,6 +24,7 @@ config.paths["converse-core"] = "builds/converse-core";
config
.
paths
[
"
converse-disco
"
]
=
"
builds/converse-disco
"
;
config
.
paths
[
"
converse-dragresize
"
]
=
"
builds/converse-dragresize
"
;
config
.
paths
[
"
converse-headline
"
]
=
"
builds/converse-headline
"
;
config
.
paths
[
"
converse-http-file-upload
"
]
=
"
builds/converse-http-file-upload
"
;
config
.
paths
[
"
converse-fullscreen
"
]
=
"
builds/converse-fullscreen
"
;
config
.
paths
[
"
converse-mam
"
]
=
"
builds/converse-mam
"
;
config
.
paths
[
"
converse-minimize
"
]
=
"
builds/converse-minimize
"
;
...
...
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