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
38d0d836
Commit
38d0d836
authored
Jun 16, 2019
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New config setting `message_limit`
for limiting messages to a certain number of characters.
parent
de3099a9
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
137 additions
and
25 deletions
+137
-25
CHANGES.md
CHANGES.md
+1
-0
docs/source/configuration.rst
docs/source/configuration.rst
+12
-0
sass/_chatbox.scss
sass/_chatbox.scss
+0
-3
spec/chatbox.js
spec/chatbox.js
+57
-0
src/converse-chatview.js
src/converse-chatview.js
+60
-20
src/converse-muc-views.js
src/converse-muc-views.js
+3
-1
src/templates/toolbar.html
src/templates/toolbar.html
+4
-1
No files found.
CHANGES.md
View file @
38d0d836
...
...
@@ -20,6 +20,7 @@
-
Replace
`moment`
with
[
DayJS
](
https://github.com/iamkun/dayjs
)
.
-
New config option
[
enable_smacks
](
https://conversejs.org/docs/html/configuration.html#enable-smacks
)
.
-
New config option
[
muc_show_join_leave_status
](
https://conversejs.org/docs/html/configuration.html#muc-show-join-leave-status
)
-
New config option
[
message_limit
](
https://conversejs.org/docs/html/configuration.html#message-limit
)
-
New config option
[
singleton
](
https://conversejs.org/docs/html/configuration.html#singleton
)
.
By setting this option to
`false`
and
`view_mode`
to
`'embedded'`
, it's now possible to
"embed" the full app and not just a single chat. To embed just a single chat, it's now
...
...
docs/source/configuration.rst
View file @
38d0d836
...
...
@@ -869,6 +869,18 @@ XEP-0280 requires server support, so make sure that message carbons are enabled
on your server.
message_limit
-------------
* Default: ``0``
Determines the allowed amount of characters in a chat message. A value of zero means there is no limit.
Note, this limitation only applies to the Converse UX code running in the browser
and it's trivial for an attacker to bypass this restriction.
You should therefore also configure your XMPP server to limit message sizes.
muc_disable_slash_commands
--------------------------
...
...
sass/_chatbox.scss
View file @
38d0d836
...
...
@@ -330,9 +330,6 @@
.private
{
color
:
#4b7003
;
}
.toggle-occupants
{
float
:
right
;
}
li
{
cursor
:
pointer
;
display
:
inline-block
;
...
...
spec/chatbox.js
View file @
38d0d836
...
...
@@ -475,6 +475,63 @@
done
();
}));
it
(
"
shows the remaining character count if a message_limit is configured
"
,
mock
.
initConverse
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
'
message_limit
'
:
200
},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitForRoster
(
_converse
,
'
current
'
,
3
);
test_utils
.
openControlBox
();
const
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@montague.lit
'
;
await
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
toolbar
=
view
.
el
.
querySelector
(
'
.chat-toolbar
'
);
const
counter
=
toolbar
.
querySelector
(
'
.message-limit
'
);
expect
(
counter
.
textContent
).
toBe
(
'
200
'
);
view
.
insertIntoTextArea
(
'
hello world
'
);
expect
(
counter
.
textContent
).
toBe
(
'
188
'
);
toolbar
.
querySelector
(
'
li.toggle-smiley
'
).
click
();
await
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
)));
var
picker
=
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
);
var
items
=
picker
.
querySelectorAll
(
'
.emoji-picker li
'
);
items
[
0
].
click
()
expect
(
counter
.
textContent
).
toBe
(
'
177
'
);
const
textarea
=
view
.
el
.
querySelector
(
'
.chat-textarea
'
);
const
ev
=
{
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
};
view
.
onKeyDown
(
ev
);
await
new
Promise
((
resolve
,
reject
)
=>
view
.
once
(
'
messageInserted
'
,
resolve
));
view
.
onKeyUp
(
ev
);
expect
(
counter
.
textContent
).
toBe
(
'
200
'
);
textarea
.
value
=
'
hello world
'
;
view
.
onKeyUp
(
ev
);
expect
(
counter
.
textContent
).
toBe
(
'
189
'
);
done
();
}));
it
(
"
does not show a remaining character count if message_limit is zero
"
,
mock
.
initConverse
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
'
message_limit
'
:
0
},
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitForRoster
(
_converse
,
'
current
'
,
3
);
test_utils
.
openControlBox
();
const
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@montague.lit
'
;
await
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
counter
=
view
.
el
.
querySelector
(
'
.chat-toolbar .message-limit
'
);
expect
(
counter
).
toBe
(
null
);
done
();
}));
it
(
"
can contain a button for starting a call
"
,
mock
.
initConverse
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
...
...
src/converse-chatview.js
View file @
38d0d836
...
...
@@ -57,6 +57,7 @@ converse.plugins.add('converse-chatview', {
_converse
.
api
.
settings
.
update
({
'
emoji_image_path
'
:
twemoji
.
default
.
base
,
'
message_limit
'
:
0
,
'
show_send_button
'
:
false
,
'
show_toolbar
'
:
true
,
'
time_format
'
:
'
HH:mm
'
,
...
...
@@ -334,6 +335,8 @@ converse.plugins.add('converse-chatview', {
'
click .upload-file
'
:
'
toggleFileUpload
'
,
'
input .chat-textarea
'
:
'
inputChanged
'
,
'
keydown .chat-textarea
'
:
'
onKeyDown
'
,
'
keyup .chat-textarea
'
:
'
onKeyUp
'
,
'
paste .chat-textarea
'
:
'
onPaste
'
,
'
dragover .chat-textarea
'
:
'
onDragOver
'
,
'
drop .chat-textarea
'
:
'
onDrop
'
,
},
...
...
@@ -381,16 +384,15 @@ converse.plugins.add('converse-chatview', {
return
this
;
},
renderToolbar
(
toolbar
,
options
)
{
renderToolbar
()
{
if
(
!
_converse
.
show_toolbar
)
{
return
this
;
}
toolbar
=
toolbar
||
tpl_toolbar
;
options
=
_
.
assign
(
const
options
=
_
.
assign
(
this
.
model
.
toJSON
(),
this
.
getToolbarOptions
(
options
||
{}
)
this
.
getToolbarOptions
()
);
this
.
el
.
querySelector
(
'
.chat-toolbar
'
).
innerHTML
=
toolbar
(
options
);
this
.
el
.
querySelector
(
'
.chat-toolbar
'
).
innerHTML
=
t
pl_t
oolbar
(
options
);
this
.
addSpoilerButton
(
options
);
this
.
addFileUploadButton
();
/**
...
...
@@ -407,6 +409,7 @@ converse.plugins.add('converse-chatview', {
const
form_container
=
this
.
el
.
querySelector
(
'
.bottom-panel
'
);
form_container
.
innerHTML
=
tpl_chatbox_message_form
(
Object
.
assign
(
this
.
model
.
toJSON
(),
{
'
message_limit
'
:
_converse
.
message_limit
,
'
hint_value
'
:
_
.
get
(
this
.
el
.
querySelector
(
'
.spoiler-hint
'
),
'
value
'
),
'
label_message
'
:
this
.
model
.
get
(
'
composing_spoiler
'
)
?
__
(
'
Hidden message
'
)
:
__
(
'
Message
'
),
'
label_send
'
:
__
(
'
Send
'
),
...
...
@@ -467,7 +470,7 @@ converse.plugins.add('converse-chatview', {
this
.
model
.
sendFiles
(
evt
.
dataTransfer
.
files
);
},
async
addFileUploadButton
(
options
)
{
async
addFileUploadButton
()
{
if
(
await
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
_converse
.
domain
))
{
this
.
el
.
querySelector
(
'
.chat-toolbar
'
).
insertAdjacentHTML
(
'
beforeend
'
,
...
...
@@ -475,11 +478,13 @@ converse.plugins.add('converse-chatview', {
}
},
/**
* Asynchronously adds a button for writing spoiler
* messages, based on whether the contact's clients support it.
* @private
* @method _converse.ChatBoxView#addSpoilerButton
*/
async
addSpoilerButton
(
options
)
{
/* Asynchronously adds a button for writing spoiler
* messages, based on whether the contact's client supports
* it.
*/
if
(
!
options
.
show_spoiler_button
||
this
.
model
.
get
(
'
type
'
)
===
_converse
.
CHATROOMS_TYPE
)
{
return
;
}
...
...
@@ -516,22 +521,24 @@ converse.plugins.add('converse-chatview', {
return
this
;
},
getToolbarOptions
(
options
)
{
getToolbarOptions
()
{
let
label_toggle_spoiler
;
if
(
this
.
model
.
get
(
'
composing_spoiler
'
))
{
label_toggle_spoiler
=
__
(
'
Click to write as a normal (non-spoiler) message
'
);
}
else
{
label_toggle_spoiler
=
__
(
'
Click to write your message as a spoiler
'
);
}
return
Object
.
assign
(
options
||
{},
{
return
{
'
label_clear
'
:
__
(
'
Clear all messages
'
),
'
tooltip_insert_smiley
'
:
__
(
'
Insert emojis
'
),
'
tooltip_start_call
'
:
__
(
'
Start a call
'
),
'
label_message_limit
'
:
__
(
'
Message characters remaining
'
),
'
label_toggle_spoiler
'
:
label_toggle_spoiler
,
'
message_limit
'
:
_converse
.
message_limit
,
'
show_call_button
'
:
_converse
.
visible_toolbar_buttons
.
call
,
'
show_spoiler_button
'
:
_converse
.
visible_toolbar_buttons
.
spoiler
,
'
tooltip_insert_smiley
'
:
__
(
'
Insert emojis
'
),
'
tooltip_start_call
'
:
__
(
'
Start a call
'
),
'
use_emoji
'
:
_converse
.
visible_toolbar_buttons
.
emoji
,
}
);
}
},
async
updateAfterMessagesFetched
()
{
...
...
@@ -905,9 +912,11 @@ converse.plugins.add('converse-chatview', {
async
onFormSubmitted
(
ev
)
{
ev
.
preventDefault
();
const
textarea
=
this
.
el
.
querySelector
(
'
.chat-textarea
'
),
message
=
textarea
.
value
;
const
textarea
=
this
.
el
.
querySelector
(
'
.chat-textarea
'
);
const
message
=
textarea
.
value
;
if
(
_converse
.
message_limit
&&
message
.
length
>
_converse
.
message_limit
)
{
return
;
}
if
(
!
message
.
replace
(
/
\s
/g
,
''
).
length
)
{
return
;
}
...
...
@@ -949,9 +958,39 @@ converse.plugins.add('converse-chatview', {
this
.
setChatState
(
_converse
.
ACTIVE
,
{
'
silent
'
:
true
});
},
updateCharCounter
(
chars
)
{
if
(
_converse
.
message_limit
)
{
const
message_limit
=
this
.
el
.
querySelector
(
'
.message-limit
'
);
const
counter
=
_converse
.
message_limit
-
chars
.
length
;
message_limit
.
textContent
=
counter
;
if
(
counter
<
1
)
{
u
.
addClass
(
'
error
'
,
message_limit
);
}
else
{
u
.
removeClass
(
'
error
'
,
message_limit
);
}
}
},
onPaste
(
ev
)
{
this
.
updateCharCounter
(
ev
.
clipboardData
.
getData
(
'
text/plain
'
));
},
/**
* Event handler for when a depressed key goes up
* @private
* @method _converse.ChatBoxView#onKeyUp
*/
onKeyUp
(
ev
)
{
this
.
updateCharCounter
(
ev
.
target
.
value
);
},
/**
* Event handler for when a key is pressed down in a chat box textarea.
* @private
* @method _converse.ChatBoxView#onKeyDown
* @param { Event } ev
*/
onKeyDown
(
ev
)
{
/* Event handler for when a key is pressed in a chat box textarea.
*/
if
(
ev
.
ctrlKey
)
{
// When ctrl is pressed, no chars are entered into the textarea.
return
;
...
...
@@ -1101,6 +1140,7 @@ converse.plugins.add('converse-chatview', {
textarea
.
value
=
''
;
textarea
.
value
=
existing
+
value
+
'
'
;
}
this
.
updateCharCounter
(
textarea
.
value
);
u
.
placeCaretAtEnd
(
textarea
);
},
...
...
src/converse-muc-views.js
View file @
38d0d836
...
...
@@ -460,6 +460,7 @@ converse.plugins.add('converse-muc-views', {
'
click .upload-file
'
:
'
toggleFileUpload
'
,
'
keydown .chat-textarea
'
:
'
onKeyDown
'
,
'
keyup .chat-textarea
'
:
'
onKeyUp
'
,
'
paste .chat-textarea
'
:
'
onPaste
'
,
'
input .chat-textarea
'
:
'
inputChanged
'
,
'
dragover .chat-textarea
'
:
'
onDragOver
'
,
'
drop .chat-textarea
'
:
'
onDrop
'
,
...
...
@@ -583,11 +584,12 @@ converse.plugins.add('converse-muc-views', {
if
(
this
.
mention_auto_complete
.
onKeyDown
(
ev
))
{
return
;
}
return
_converse
.
ChatBoxView
.
prototype
.
onKeyDown
.
apply
(
this
,
arguments
);
return
_converse
.
ChatBoxView
.
prototype
.
onKeyDown
.
call
(
this
,
ev
);
},
onKeyUp
(
ev
)
{
this
.
mention_auto_complete
.
evaluate
(
ev
);
return
_converse
.
ChatBoxView
.
prototype
.
onKeyUp
.
call
(
this
,
ev
);
},
showRoomDetailsModal
(
ev
)
{
...
...
src/templates/toolbar.html
View file @
38d0d836
...
...
@@ -8,6 +8,9 @@
<li
class=
"toggle-call fa fa-phone"
title=
"{{{o.label_start_call}}}"
></li>
{[ } ]}
{[ if (o.show_occupants_toggle) { ]}
<li
class=
"toggle-occupants fa {[ if (o.hidden_occupants) { ]} fa-angle-double-left {[ } else { ]} fa-angle-double-right {[ } ]}"
<li
class=
"toggle-occupants f
loat-right f
a {[ if (o.hidden_occupants) { ]} fa-angle-double-left {[ } else { ]} fa-angle-double-right {[ } ]}"
title=
"{{{o.label_hide_occupants}}}"
></li>
{[ } ]}
{[ if (o.message_limit) { ]}
<li
class=
"message-limit font-weight-bold float-right"
title=
"{{{o.label_message_limit}}}"
>
{{{o.message_limit}}}
</li>
{[ } ]}
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