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
ac36addd
Commit
ac36addd
authored
Jun 01, 2020
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Re-add support for a new messages indicator
Fixes #2040
parent
ccd817cc
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
64 additions
and
45 deletions
+64
-45
spec/chatbox.js
spec/chatbox.js
+2
-2
spec/messages.js
spec/messages.js
+24
-0
spec/mock.js
spec/mock.js
+1
-1
spec/presence.js
spec/presence.js
+2
-1
src/components/message-history.js
src/components/message-history.js
+17
-16
src/components/message.js
src/components/message.js
+5
-4
src/headless/converse-chat.js
src/headless/converse-chat.js
+7
-19
src/headless/converse-muc.js
src/headless/converse-muc.js
+6
-2
No files found.
spec/chatbox.js
View file @
ac36addd
...
...
@@ -1353,7 +1353,7 @@ describe("Chatboxes", function () {
done
();
}));
it
(
"
is incremeted when message is received, chatbox is scrolled down and the window is not focused
"
,
it
(
"
is increme
n
ted when message is received, chatbox is scrolled down and the window is not focused
"
,
mock
.
initConverse
([
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
async
function
(
done
,
_converse
)
{
...
...
@@ -1375,7 +1375,7 @@ describe("Chatboxes", function () {
done
();
}));
it
(
"
is incremeted when message is received, chatbox is scrolled up and the window is not focused
"
,
it
(
"
is increme
n
ted when message is received, chatbox is scrolled up and the window is not focused
"
,
mock
.
initConverse
(
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
async
function
(
done
,
_converse
)
{
...
...
spec/messages.js
View file @
ac36addd
...
...
@@ -6,6 +6,30 @@ const u = converse.env.utils;
describe
(
"
A Chat Message
"
,
function
()
{
it
(
"
will be demarcated if it's the first newly received message
"
,
mock
.
initConverse
([
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
async
function
(
done
,
_converse
)
{
await
mock
.
waitForRoster
(
_converse
,
'
current
'
,
1
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@montague.lit
'
;
await
mock
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
api
.
chatviews
.
get
(
contact_jid
);
await
_converse
.
handleMessageStanza
(
mock
.
createChatMessage
(
_converse
,
contact_jid
,
'
This message will be read
'
));
_converse
.
windowState
=
'
hidden
'
;
await
_converse
.
handleMessageStanza
(
mock
.
createChatMessage
(
_converse
,
contact_jid
,
'
This message will be new
'
));
await
u
.
waitUntil
(()
=>
view
.
model
.
messages
.
length
);
expect
(
view
.
model
.
get
(
'
num_unread
'
)).
toBe
(
1
);
expect
(
view
.
model
.
get
(
'
first_unread_id
'
)).
toBe
(
view
.
model
.
messages
.
last
().
get
(
'
id
'
));
await
u
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
converse-chat-message
'
).
length
===
2
);
const
last_msg_el
=
view
.
el
.
querySelector
(
'
converse-chat-message:last-child
'
);
expect
(
last_msg_el
.
firstElementChild
?.
textContent
).
toBe
(
'
New messages
'
);
done
();
}));
it
(
"
is rejected if it's an unencapsulated forwarded message
"
,
mock
.
initConverse
(
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
...
...
spec/mock.js
View file @
ac36addd
...
...
@@ -4,7 +4,7 @@ let _converse, initConverse;
const
converseLoaded
=
new
Promise
(
resolve
=>
window
.
addEventListener
(
'
converse-loaded
'
,
resolve
));
jasmine
.
DEFAULT_TIMEOUT_INTERVAL
=
5
000
;
jasmine
.
DEFAULT_TIMEOUT_INTERVAL
=
7
000
;
mock
.
initConverse
=
function
(
promise_names
=
[],
settings
=
null
,
func
)
{
if
(
typeof
promise_names
===
"
function
"
)
{
...
...
spec/presence.js
View file @
ac36addd
...
...
@@ -74,7 +74,8 @@ describe("A sent presence stanza", function () {
spyOn
(
_converse
.
connection
,
'
send
'
).
and
.
callThrough
();
const
cbview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
cbview
.
el
.
querySelector
(
'
.change-status
'
).
click
()
const
change_status_el
=
await
u
.
waitUntil
(()
=>
cbview
.
el
.
querySelector
(
'
.change-status
'
));
change_status_el
.
click
()
const
modal
=
_converse
.
xmppstatusview
.
status_modal
;
await
u
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
const
msg
=
'
My custom status
'
;
...
...
src/components/message-history.js
View file @
ac36addd
...
...
@@ -20,6 +20,7 @@ const tpl_message = (o) => html`
?has_mentions=
${
o
.
has_mentions
}
?is_delayed=
${
o
.
is_delayed
}
?is_encrypted=
${
o
.
is_encrypted
}
?is_first_unread=
${
o
.
is_first_unread
}
?is_me_message=
${
o
.
is_me_message
}
?is_only_emojis=
${
o
.
is_only_emojis
}
?is_retracted=
${
o
.
is_retracted
}
...
...
@@ -67,6 +68,18 @@ function getDayIndicator (model) {
}
}
function
getHats
(
model
)
{
if
(
model
.
get
(
'
type
'
)
===
'
groupchat
'
)
{
if
(
api
.
settings
.
get
(
'
muc_hats_from_vcard
'
))
{
const
role
=
model
.
vcard
?
model
.
vcard
.
get
(
'
role
'
)
:
null
;
return
role
?
role
.
split
(
'
,
'
)
:
[];
}
else
{
return
model
.
occupant
?.
get
(
'
hats
'
)
||
[];
}
}
return
[];
}
class
MessageHistory
extends
CustomElement
{
...
...
@@ -91,30 +104,18 @@ class MessageHistory extends CustomElement {
}
const
day
=
getDayIndicator
(
model
);
const
templates
=
day
?
[
day
]
:
[];
const
is_retracted
=
model
.
get
(
'
retracted
'
)
||
model
.
get
(
'
moderated
'
)
===
'
retracted
'
;
const
is_groupchat
=
model
.
get
(
'
type
'
)
===
'
groupchat
'
;
let
hats
=
[];
if
(
is_groupchat
)
{
if
(
api
.
settings
.
get
(
'
muc_hats_from_vcard
'
))
{
const
role
=
model
.
vcard
?
model
.
vcard
.
get
(
'
role
'
)
:
null
;
hats
=
role
?
role
.
split
(
'
,
'
)
:
[];
}
else
{
hats
=
model
.
occupant
?.
get
(
'
hats
'
)
||
[];
}
}
const
chatbox
=
this
.
chatview
.
model
;
const
has_mentions
=
is_groupchat
&&
model
.
get
(
'
sender
'
)
===
'
them
'
&&
chatbox
.
isUserMentioned
(
model
);
const
message
=
tpl_message
(
Object
.
assign
(
model
.
toJSON
(),
{
'
chatview
'
:
this
.
chatview
,
'
has_mentions
'
:
is_groupchat
&&
model
.
get
(
'
sender
'
)
===
'
them
'
&&
chatbox
.
isUserMentioned
(
model
),
'
hats
'
:
getHats
(
model
),
'
is_first_unread
'
:
chatbox
.
get
(
'
first_unread_id
'
)
===
model
.
get
(
'
id
'
),
'
is_me_message
'
:
model
.
isMeCommand
(),
'
is_retracted
'
:
model
.
get
(
'
retracted
'
)
||
model
.
get
(
'
moderated
'
)
===
'
retracted
'
,
'
occupant
'
:
model
.
occupant
,
'
username
'
:
model
.
getDisplayName
(),
has_mentions
,
hats
,
is_retracted
,
model
,
}));
return
[...
templates
,
message
];
...
...
src/components/message.js
View file @
ac36addd
...
...
@@ -17,7 +17,8 @@ const i18n_edit_message = __('Edit this message');
const
i18n_edited
=
__
(
'
This message has been edited
'
);
const
i18n_show
=
__
(
'
Show more
'
);
const
i18n_show_less
=
__
(
'
Show less
'
);
const
i18n_uploading
=
__
(
'
Uploading file:
'
)
const
i18n_uploading
=
__
(
'
Uploading file:
'
);
const
i18n_new_messages
=
__
(
'
New messages
'
);
class
Message
extends
CustomElement
{
...
...
@@ -30,19 +31,19 @@ class Message extends CustomElement {
editable
:
{
type
:
Boolean
},
error
:
{
type
:
String
},
error_text
:
{
type
:
String
},
first_unread
:
{
type
:
Boolean
},
from
:
{
type
:
String
},
has_mentions
:
{
type
:
Boolean
},
hats
:
{
type
:
Array
},
edited
:
{
type
:
String
},
is_delayed
:
{
type
:
Boolean
},
is_encrypted
:
{
type
:
Boolean
},
is_first_unread
:
{
type
:
Boolean
},
is_me_message
:
{
type
:
Boolean
},
is_only_emojis
:
{
type
:
Boolean
},
is_retracted
:
{
type
:
Boolean
},
is_spoiler
:
{
type
:
Boolean
},
is_spoiler_visible
:
{
type
:
Boolean
},
message_type
:
{
type
:
String
},
edited
:
{
type
:
String
},
model
:
{
type
:
Object
},
moderated_by
:
{
type
:
String
},
moderation_reason
:
{
type
:
String
},
...
...
@@ -125,6 +126,7 @@ class Message extends CustomElement {
renderChatMessage
()
{
const
is_groupchat_message
=
(
this
.
message_type
===
'
groupchat
'
);
return
html
`
${
this
.
is_first_unread
?
html
`<div class="message date-separator"><hr class="separator"><span class="separator-text">
${
i18n_new_messages
}
</span></div>`
:
''
}
<div class="message chat-msg
${
this
.
message_type
}
${
this
.
getExtraMessageClasses
()}
${
this
.
is_me_message
?
'
chat-msg--action
'
:
''
}
${
this
.
isFollowup
()
?
'
chat-msg--followup
'
:
''
}
"
...
...
@@ -132,7 +134,6 @@ class Message extends CustomElement {
${
renderAvatar
(
this
)
}
<div class="chat-msg__content chat-msg__content--
${
this
.
sender
}
${
this
.
is_me_message
?
'
chat-msg__content--action
'
:
''
}
">
${
this
.
first_unread
?
html
`<div class="message date-separator"><hr class="separator"><span class="separator-text">{{{this.__('unread messages')}}}</span></div>`
:
''
}
<span class="chat-msg__heading">
${
(
this
.
is_me_message
)
?
html
`
<time timestamp="
${
this
.
time
}
" class="chat-msg__time">
${
this
.
pretty_time
}
</time>
...
...
src/headless/converse-chat.js
View file @
ac36addd
...
...
@@ -1145,26 +1145,14 @@ converse.plugins.add('converse-chat', {
return
;
}
if
(
utils
.
isNewMessage
(
message
)
&&
this
.
isHidden
())
{
this
.
setFirstUnreadMsgId
(
message
);
this
.
save
({
'
num_unread
'
:
this
.
get
(
'
num_unread
'
)
+
1
});
_converse
.
incrementMsgCounter
();
}
},
/**
* Sets the msgid of the first unread realtime message in a ChatBox.
* @param {_converse.Message} message
*/
setFirstUnreadMsgId
(
message
)
{
if
(
this
.
get
(
'
num_unread
'
)
==
0
)
{
const
first_unread_id
=
this
.
get
(
'
first_unread_id
'
);
if
(
first_unread_id
)
{
const
msg
=
this
.
messages
.
get
(
first_unread_id
);
if
(
msg
)
msg
.
save
(
"
first_unread
"
,
false
);
const
settings
=
{
'
num_unread
'
:
this
.
get
(
'
num_unread
'
)
+
1
};
if
(
this
.
get
(
'
num_unread
'
)
===
0
)
{
settings
[
'
first_unread_id
'
]
=
message
.
get
(
'
id
'
);
}
message
.
save
(
"
first_unread
"
,
true
);
this
.
save
({
'
first_unread_id
'
:
message
.
get
(
'
id
'
)}
);
this
.
save
(
settings
);
_converse
.
incrementMsgCounter
(
);
}
},
...
...
src/headless/converse-muc.js
View file @
ac36addd
...
...
@@ -2408,8 +2408,12 @@ converse.plugins.add('converse-muc', {
const
body
=
message
.
get
(
'
message
'
);
if
(
!
body
)
{
return
;
}
if
(
u
.
isNewMessage
(
message
)
&&
this
.
isHidden
())
{
this
.
setFirstUnreadMsgId
(
message
);
const
settings
=
{
'
num_unread_general
'
:
this
.
get
(
'
num_unread_general
'
)
+
1
};
const
settings
=
{
'
num_unread_general
'
:
this
.
get
(
'
num_unread_general
'
)
+
1
};
if
(
this
.
get
(
'
num_unread
'
)
===
0
)
{
settings
[
'
first_unread_id
'
]
=
message
.
get
(
'
id
'
);
}
if
(
this
.
isUserMentioned
(
message
))
{
settings
.
num_unread
=
this
.
get
(
'
num_unread
'
)
+
1
;
_converse
.
incrementMsgCounter
();
...
...
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