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
b7eb19e2
Commit
b7eb19e2
authored
Aug 16, 2018
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Render mentions in a message
parent
15df9b86
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
102 additions
and
18 deletions
+102
-18
CHANGES.md
CHANGES.md
+2
-1
css/converse.css
css/converse.css
+4
-3
sass/_chatrooms.scss
sass/_chatrooms.scss
+0
-3
sass/_messages.scss
sass/_messages.scss
+6
-0
spec/messages.js
spec/messages.js
+55
-9
src/converse-chatboxes.js
src/converse-chatboxes.js
+13
-0
src/converse-message-view.js
src/converse-message-view.js
+1
-0
src/converse-muc.js
src/converse-muc.js
+2
-2
src/utils/core.js
src/utils/core.js
+19
-0
No files found.
CHANGES.md
View file @
b7eb19e2
...
...
@@ -21,8 +21,9 @@
-
Add a checkbox to indicate whether a trusted device is being used or not.
If the device is not trusted, sessionStorage is used and all user data is deleted from the browser cache upon logout.
If the device is trusted, localStorage is used and user data is cached indefinitely.
-
Initial support for
XEP-0357 Push Notifications
, specifically registering an "App Server".
-
Initial support for
[
XEP-0357 Push Notifications
](
https://xmpp.org/extensions/xep-0357.html
)
, specifically registering an "App Server".
-
Add support for logging in via OAuth (see the
[
oauth_providers
](
https://conversejs.org/docs/html/configurations.html#oauth-providers
)
setting)
-
Add support for
[
XEP-0372 References
](
https://xmpp.org/extensions/xep-0372.html
)
, specifically section "3.2 Mentions".
### Bugfixes
...
...
css/converse.css
View file @
b7eb19e2
...
...
@@ -8540,9 +8540,6 @@ body.reset {
#conversejs
.converse-embedded
.chatroom
.box-flyout
.chatroom-body
.chat-info.badge
,
#conversejs
.chatroom
.box-flyout
.chatroom-body
.chat-info.badge
{
color
:
white
;
}
#conversejs
.converse-embedded
.chatroom
.box-flyout
.chatroom-body
.mentioned
,
#conversejs
.chatroom
.box-flyout
.chatroom-body
.mentioned
{
font-weight
:
bold
;
}
#conversejs
.converse-embedded
.chatroom
.box-flyout
.chatroom-body
.disconnect-container
,
#conversejs
.chatroom
.box-flyout
.chatroom-body
.disconnect-container
{
margin
:
1em
;
...
...
@@ -8799,6 +8796,10 @@ body.reset {
border
:
1.2em
solid
#E7A151
;
border-top
:
0.8em
solid
#E7A151
;
}
#conversejs
.message
.mention
{
font-weight
:
bold
;
}
#conversejs
.message
.mention--self
{
font-weight
:
normal
;
}
#conversejs
.message.date-separator
{
height
:
2em
;
margin
:
0
;
...
...
sass/_chatrooms.scss
View file @
b7eb19e2
...
...
@@ -116,9 +116,6 @@
color
:
$chat-head-text-color
;
}
}
.mentioned
{
font-weight
:
bold
;
}
.disconnect-container
{
margin
:
1em
;
width
:
100%
;
...
...
sass/_messages.scss
View file @
b7eb19e2
#conversejs
{
.message
{
.mention
{
font-weight
:
bold
;
}
.mention--self
{
font-weight
:
normal
;
}
&
.date-separator
{
height
:
2em
;
margin
:
0
;
...
...
spec/messages.js
View file @
b7eb19e2
...
...
@@ -2089,6 +2089,52 @@
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
}));
describe
(
"
when received
"
,
function
()
{
it
(
"
highlights all users mentioned via XEP-0372 references
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
tom
'
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
[
'
z3r0
'
,
'
mr.robot
'
,
'
gibson
'
,
'
sw0rdf1sh
'
].
forEach
((
nick
)
=>
{
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
$pres
({
'
to
'
:
'
tom@localhost/resource
'
,
'
from
'
:
`lounge@localhost/
${
nick
}
`
})
.
c
(
'
x
'
,
{
xmlns
:
Strophe
.
NS
.
MUC_USER
})
.
c
(
'
item
'
,
{
'
affiliation
'
:
'
none
'
,
'
jid
'
:
`
${
nick
}
@localhost/resource`
,
'
role
'
:
'
participant
'
}))
);
});
const
msg
=
$msg
({
from
:
'
lounge@localhost/gibson
'
,
id
:
(
new
Date
()).
getTime
(),
to
:
'
dummy@localhost
'
,
type
:
'
groupchat
'
}).
c
(
'
body
'
).
t
(
'
hello z3r0 tom mr.robot, how are you?
'
).
up
()
.
c
(
'
reference
'
,
{
'
xmlns
'
:
'
urn:xmpp:reference:0
'
,
'
begin
'
:
'
6
'
,
'
end
'
:
'
10
'
,
'
type
'
:
'
mention
'
,
'
uri
'
:
'
xmpp:z3r0@localhost
'
}).
up
()
.
c
(
'
reference
'
,
{
'
xmlns
'
:
'
urn:xmpp:reference:0
'
,
'
begin
'
:
'
11
'
,
'
end
'
:
'
14
'
,
'
type
'
:
'
mention
'
,
'
uri
'
:
'
xmpp:dummy@localhost
'
}).
up
()
.
c
(
'
reference
'
,
{
'
xmlns
'
:
'
urn:xmpp:reference:0
'
,
'
begin
'
:
'
15
'
,
'
end
'
:
'
23
'
,
'
type
'
:
'
mention
'
,
'
uri
'
:
'
xmpp:mr.robot@localhost
'
}).
nodeTree
;
view
.
model
.
onMessage
(
msg
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg__text
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-msg__text
'
).
outerHTML
).
toBe
(
'
<div class="chat-msg__text">hello <span class="mention">z3r0</span>
'
+
'
<span class="mention mention--self badge badge-info">tom</span>
'
+
'
<span class="mention">mr.robot</span>, how are you?</div>
'
);
done
();
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
}));
});
describe
(
"
in which someone is mentioned
"
,
function
()
{
it
(
"
gets parsed for mentions which get turned into references
"
,
...
...
@@ -2113,33 +2159,33 @@
})));
});
// Run a few unit tests for the parseForReferences method
let
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
hello z3r0
'
)
// Run a few unit tests for the parse
Text
ForReferences method
let
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
hello z3r0
'
)
expect
(
references
.
length
).
toBe
(
0
);
expect
(
text
).
toBe
(
'
hello z3r0
'
);
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
hello @z3r0
'
)
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
hello @z3r0
'
)
expect
(
references
.
length
).
toBe
(
1
);
expect
(
text
).
toBe
(
'
hello z3r0
'
);
expect
(
JSON
.
stringify
(
references
))
.
toBe
(
'
[{"begin":6,"end":10,"type":"mention","uri":"xmpp:z3r0@localhost"}]
'
);
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
hello @some1 @z3r0 @gibson @mr.robot, how are you?
'
)
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
hello @some1 @z3r0 @gibson @mr.robot, how are you?
'
)
expect
(
text
).
toBe
(
'
hello @some1 z3r0 gibson mr.robot, how are you?
'
);
expect
(
JSON
.
stringify
(
references
))
.
toBe
(
'
[{"begin":13,"end":17,"type":"mention","uri":"xmpp:z3r0@localhost"},
'
+
'
{"begin":18,"end":24,"type":"mention","uri":"xmpp:gibson@localhost"},
'
+
'
{"begin":25,"end":33,"type":"mention","uri":"xmpp:mr.robot@localhost"}]
'
);
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
yo @gib
'
)
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
yo @gib
'
)
expect
(
text
).
toBe
(
'
yo @gib
'
);
expect
(
references
.
length
).
toBe
(
0
);
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
yo @gibsonian
'
)
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
yo @gibsonian
'
)
expect
(
text
).
toBe
(
'
yo @gibsonian
'
);
expect
(
references
.
length
).
toBe
(
0
);
[
text
,
references
]
=
view
.
model
.
parseForReferences
(
'
@gibson
'
)
[
text
,
references
]
=
view
.
model
.
parse
Text
ForReferences
(
'
@gibson
'
)
expect
(
text
).
toBe
(
'
gibson
'
);
expect
(
references
.
length
).
toBe
(
1
);
expect
(
JSON
.
stringify
(
references
))
...
...
@@ -2190,9 +2236,9 @@
`xmlns='jabber:client'>`
+
`<body>hello z3r0 gibson mr.robot, how are you?</body>`
+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`
+
`<reference xmlns='urn:xmpp:reference:0' begin='6' end='10' type='mention' uri='xmpp:z3r0@localhost'/>`
+
`<reference xmlns='urn:xmpp:reference:0' begin='11' end='17' type='mention' uri='xmpp:gibson@localhost'/>`
+
`<reference xmlns='urn:xmpp:reference:0' begin='18' end='26' type='mention' uri='xmpp:mr.robot@localhost'/>`
+
`<reference xmlns='urn:xmpp:reference:0' begin='11' end='17' type='mention' uri='xmpp:gibson@localhost'/>`
+
`<reference xmlns='urn:xmpp:reference:0' begin='6' end='10' type='mention' uri='xmpp:z3r0@localhost'/>`
+
`</message>`
);
done
();
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
...
...
src/converse-chatboxes.js
View file @
b7eb19e2
...
...
@@ -299,6 +299,7 @@
older_versions
.
push
(
message
.
get
(
'
message
'
));
message
.
save
({
'
message
'
:
_converse
.
chatboxes
.
getMessageBody
(
stanza
),
'
references
'
:
this
.
getReferencesFromStanza
(
stanza
),
'
older_versions
'
:
older_versions
,
'
edited
'
:
true
});
...
...
@@ -459,6 +460,17 @@
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
));
},
getReferencesFromStanza
(
stanza
)
{
return
sizzle
(
`reference[xmlns="
${
Strophe
.
NS
.
REFERENCE
}
"]`
,
stanza
).
map
(
ref
=>
{
return
{
'
begin
'
:
ref
.
getAttribute
(
'
begin
'
),
'
end
'
:
ref
.
getAttribute
(
'
end
'
),
'
type
'
:
ref
.
getAttribute
(
'
type
'
),
'
uri
'
:
ref
.
getAttribute
(
'
uri
'
)
};
});
},
getMessageAttributesFromStanza
(
stanza
,
original_stanza
)
{
/* Parses a passed in message stanza and returns an object
* of attributes.
...
...
@@ -488,6 +500,7 @@
'
is_delayed
'
:
!
_
.
isNil
(
delay
),
'
is_spoiler
'
:
!
_
.
isNil
(
spoiler
),
'
message
'
:
_converse
.
chatboxes
.
getMessageBody
(
stanza
)
||
undefined
,
'
references
'
:
this
.
getReferencesFromStanza
(
stanza
),
'
msgid
'
:
stanza
.
getAttribute
(
'
id
'
),
'
time
'
:
delay
?
delay
.
getAttribute
(
'
stamp
'
)
:
moment
().
format
(),
'
type
'
:
stanza
.
getAttribute
(
'
type
'
)
...
...
src/converse-message-view.js
View file @
b7eb19e2
...
...
@@ -167,6 +167,7 @@
text
=
xss
.
filterXSS
(
text
,
{
'
whiteList
'
:
{}});
msg_content
.
innerHTML
=
_
.
flow
(
_
.
partial
(
u
.
geoUriToHttp
,
_
,
_converse
.
geouri_replacement
),
_
.
partial
(
u
.
addMentions
,
_
,
this
.
model
.
get
(
'
references
'
),
this
.
model
.
collection
.
chatbox
),
u
.
addHyperlinks
,
u
.
renderNewLines
,
_
.
partial
(
u
.
addEmoji
,
_converse
,
emojione
,
_
)
...
...
src/converse-muc.js
View file @
b7eb19e2
...
...
@@ -349,7 +349,7 @@
return
;
},
parseForReferences
(
text
)
{
parse
Text
ForReferences
(
text
)
{
const
refs
=
[];
let
index
=
0
;
while
(
index
<
(
text
||
''
).
length
)
{
...
...
@@ -368,7 +368,7 @@
getOutgoingMessageAttributes
(
text
,
spoiler_hint
)
{
const
is_spoiler
=
this
.
get
(
'
composing_spoiler
'
);
var
references
;
[
text
,
references
]
=
this
.
parseForReferences
(
text
);
[
text
,
references
]
=
this
.
parse
Text
ForReferences
(
text
);
return
{
'
from
'
:
`
${
this
.
get
(
'
jid
'
)}
/
${
this
.
get
(
'
nick
'
)}
`
,
...
...
src/utils/core.js
View file @
b7eb19e2
...
...
@@ -229,6 +229,25 @@
return
encodeURI
(
decodeURI
(
url
)).
replace
(
/
[
!'()
]
/g
,
escape
).
replace
(
/
\*
/g
,
"
%2A
"
);
};
u
.
addMentions
=
function
(
text
,
references
,
chatbox
)
{
if
(
chatbox
.
get
(
'
message_type
'
)
!==
'
groupchat
'
)
{
return
text
;
}
const
nick
=
chatbox
.
get
(
'
nick
'
);
references
.
sort
((
a
,
b
)
=>
b
.
begin
-
a
.
begin
)
.
forEach
(
ref
=>
{
const
mention
=
text
.
slice
(
ref
.
begin
,
ref
.
end
)
chatbox
;
if
(
mention
===
nick
)
{
text
=
text
.
slice
(
0
,
ref
.
begin
)
+
`<span class="mention mention--self badge badge-info">
${
mention
}
</span>`
+
text
.
slice
(
ref
.
end
);
}
else
{
text
=
text
.
slice
(
0
,
ref
.
begin
)
+
`<span class="mention">
${
mention
}
</span>`
+
text
.
slice
(
ref
.
end
);
}
});
return
text
;
};
u
.
addHyperlinks
=
function
(
text
)
{
return
URI
.
withinString
(
text
,
function
(
url
)
{
var
uri
=
new
URI
(
url
);
...
...
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