Indicate to the user when there are unread messages
further down in the chat box.
This commit is contained in:
parent
82ee7f694e
commit
c738d085c4
@ -1369,6 +1369,16 @@
|
|||||||
color: #FB5D50; }
|
color: #FB5D50; }
|
||||||
#conversejs .chatbox .chat-body .delayed .chat-msg-me {
|
#conversejs .chatbox .chat-body .delayed .chat-msg-me {
|
||||||
color: #7EABBB; }
|
color: #7EABBB; }
|
||||||
|
#conversejs .chatbox .new-msgs-indicator {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #F4A261;
|
||||||
|
color: #FCFDFD;
|
||||||
|
padding: 0.3em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 20; }
|
||||||
#conversejs .chatbox .chat-content {
|
#conversejs .chatbox .chat-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@ -1455,7 +1465,7 @@
|
|||||||
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
||||||
display: none;
|
display: none;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin: 0 0 1px 0;
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0; }
|
right: 0; }
|
||||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar ul li {
|
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar ul li {
|
||||||
@ -1985,10 +1995,15 @@
|
|||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
float: left;
|
float: left;
|
||||||
min-width: 200px; }
|
min-width: 200px; }
|
||||||
|
#conversejs .chatroom .box-flyout .chatroom-body .chat-area .new-msgs-indicator {
|
||||||
|
background-color: #E76F51;
|
||||||
|
max-width: 70%; }
|
||||||
#conversejs .chatroom .box-flyout .chatroom-body .chat-area .chat-content {
|
#conversejs .chatroom .box-flyout .chatroom-body .chat-area .chat-content {
|
||||||
padding: 0 0.5em 0 0.5em; }
|
padding: 0 0.5em 0 0.5em; }
|
||||||
#conversejs .chatroom .box-flyout .chatroom-body .chat-area.full {
|
#conversejs .chatroom .box-flyout .chatroom-body .chat-area.full {
|
||||||
max-width: 100%; }
|
max-width: 100%; }
|
||||||
|
#conversejs .chatroom .box-flyout .chatroom-body .chat-area.full .new-msgs-indicator {
|
||||||
|
max-width: 100%; }
|
||||||
#conversejs .chatroom .box-flyout .chatroom-body .mentioned {
|
#conversejs .chatroom .box-flyout .chatroom-body .mentioned {
|
||||||
font-weight: bold; }
|
font-weight: bold; }
|
||||||
#conversejs .chatroom .box-flyout .chatroom-body .chat-msg-room {
|
#conversejs .chatroom .box-flyout .chatroom-body .chat-msg-room {
|
||||||
|
@ -187,6 +187,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.new-msgs-indicator {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: $chat-head-color;
|
||||||
|
color: $light-background-color;
|
||||||
|
padding: 0.3em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
.chat-content {
|
.chat-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@ -283,7 +294,7 @@
|
|||||||
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
||||||
display: none;
|
display: none;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin: 0 0 1px 0;
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
li {
|
li {
|
||||||
|
@ -50,12 +50,19 @@
|
|||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
float: left;
|
float: left;
|
||||||
min-width: $chat-width;
|
min-width: $chat-width;
|
||||||
|
.new-msgs-indicator {
|
||||||
|
background-color: $chatroom-head-color;
|
||||||
|
max-width: 70%;
|
||||||
|
}
|
||||||
.chat-content {
|
.chat-content {
|
||||||
// There's an annoying Chrome box-sizing bug which prevents us from adding 0.5em padding here.
|
// There's an annoying Chrome box-sizing bug which prevents us from adding 0.5em padding here.
|
||||||
padding: 0 0.5em 0 0.5em;
|
padding: 0 0.5em 0 0.5em;
|
||||||
}
|
}
|
||||||
&.full {
|
&.full {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
.new-msgs-indicator {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.mentioned {
|
.mentioned {
|
||||||
|
@ -413,19 +413,7 @@
|
|||||||
runs(function () {});
|
runs(function () {});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe("when received from someone else", function () {
|
describe("when received from someone else", function () {
|
||||||
it("will cause the chat area to be scrolled down only if it was at the bottom already", function () {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when sent by the current user", function () {
|
|
||||||
it("will always cause the chat area to be scrolled down", function () {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can be received which will open a chatbox and be displayed inside it", function () {
|
it("can be received which will open a chatbox and be displayed inside it", function () {
|
||||||
spyOn(converse, 'emit');
|
spyOn(converse, 'emit');
|
||||||
var message = 'This is a received message';
|
var message = 'This is a received message';
|
||||||
@ -469,6 +457,58 @@
|
|||||||
}.bind(converse));
|
}.bind(converse));
|
||||||
}.bind(converse));
|
}.bind(converse));
|
||||||
|
|
||||||
|
it("will cause the chat area to be scrolled down only if it was at the bottom already", function () {
|
||||||
|
var message = 'This message is received while the chat area is scrolled up';
|
||||||
|
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
test_utils.openChatBoxFor(sender_jid);
|
||||||
|
var chatboxview = converse.chatboxviews.get(sender_jid);
|
||||||
|
spyOn(chatboxview, 'scrollDown').andCallThrough();
|
||||||
|
runs(function () {
|
||||||
|
/* Create enough messages so that there's a
|
||||||
|
* scrollbar.
|
||||||
|
*/
|
||||||
|
for (var i=0; i<20; i++) {
|
||||||
|
converse.chatboxes.onMessage($msg({
|
||||||
|
from: sender_jid,
|
||||||
|
to: converse.connection.jid,
|
||||||
|
type: 'chat',
|
||||||
|
id: (new Date()).getTime()
|
||||||
|
}).c('body').t('Message: '+i).up()
|
||||||
|
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
waits(50);
|
||||||
|
runs(function () {
|
||||||
|
chatboxview.$content.scrollTop(0);
|
||||||
|
});
|
||||||
|
waits(250);
|
||||||
|
runs(function () {
|
||||||
|
converse.chatboxes.onMessage($msg({
|
||||||
|
from: sender_jid,
|
||||||
|
to: converse.connection.jid,
|
||||||
|
type: 'chat',
|
||||||
|
id: (new Date()).getTime()
|
||||||
|
}).c('body').t(message).up()
|
||||||
|
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
|
||||||
|
});
|
||||||
|
waits(150);
|
||||||
|
runs(function () {
|
||||||
|
// Now check that the message appears inside the chatbox in the DOM
|
||||||
|
var $chat_content = chatboxview.$el.find('.chat-content');
|
||||||
|
var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
|
||||||
|
expect(msg_txt).toEqual(message);
|
||||||
|
expect(chatboxview.model.get('scrolled')).toBeTruthy();
|
||||||
|
expect(chatboxview.$content.scrollTop()).toBe(0);
|
||||||
|
expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeTruthy();
|
||||||
|
// Scroll down again
|
||||||
|
chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight);
|
||||||
|
});
|
||||||
|
waits(250);
|
||||||
|
runs(function () {
|
||||||
|
expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("is ignored if it's intended for a different resource and filter_by_resource is set to true", function () {
|
it("is ignored if it's intended for a different resource and filter_by_resource is set to true", function () {
|
||||||
// Send a message from a different resource
|
// Send a message from a different resource
|
||||||
var message, sender_jid, msg;
|
var message, sender_jid, msg;
|
||||||
@ -514,6 +554,13 @@
|
|||||||
expect(msg_txt).toEqual(message);
|
expect(msg_txt).toEqual(message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when sent by the current user", function () {
|
||||||
|
it("will always cause the chat area to be scrolled down", function () {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("is ignored if it's a malformed headline message", function () {
|
it("is ignored if it's a malformed headline message", function () {
|
||||||
/* Ideally we wouldn't have to filter out headline
|
/* Ideally we wouldn't have to filter out headline
|
||||||
|
@ -216,6 +216,50 @@
|
|||||||
expect(converse.emit.callCount, 1);
|
expect(converse.emit.callCount, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("will cause the chat area to be scrolled down only if it was at the bottom already", function () {
|
||||||
|
var message = 'This message is received while the chat area is scrolled up';
|
||||||
|
test_utils.openChatRoom('lounge', 'localhost', 'dummy');
|
||||||
|
var view = converse.chatboxviews.get('lounge@localhost');
|
||||||
|
spyOn(view, 'scrollDown').andCallThrough();
|
||||||
|
runs(function () {
|
||||||
|
/* Create enough messages so that there's a
|
||||||
|
* scrollbar.
|
||||||
|
*/
|
||||||
|
for (var i=0; i<20; i++) {
|
||||||
|
converse.chatboxes.onMessage(
|
||||||
|
$msg({
|
||||||
|
from: 'lounge@localhost/someone',
|
||||||
|
to: 'dummy@localhost.com',
|
||||||
|
type: 'groupchat',
|
||||||
|
id: (new Date()).getTime(),
|
||||||
|
}).c('body').t('Message: '+i).tree());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
waits(50);
|
||||||
|
runs(function () {
|
||||||
|
view.$content.scrollTop(0);
|
||||||
|
});
|
||||||
|
waits(250);
|
||||||
|
runs(function () {
|
||||||
|
expect(view.model.get('scrolled')).toBeTruthy();
|
||||||
|
converse.chatboxes.onMessage(
|
||||||
|
$msg({
|
||||||
|
from: 'lounge@localhost/someone',
|
||||||
|
to: 'dummy@localhost.com',
|
||||||
|
type: 'groupchat',
|
||||||
|
id: (new Date()).getTime(),
|
||||||
|
}).c('body').t(message).tree());
|
||||||
|
});
|
||||||
|
waits(150);
|
||||||
|
runs(function () {
|
||||||
|
// Now check that the message appears inside the chatbox in the DOM
|
||||||
|
var $chat_content = view.$el.find('.chat-content');
|
||||||
|
var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
|
||||||
|
expect(msg_txt).toEqual(message);
|
||||||
|
expect(view.$content.scrollTop()).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("shows received chatroom subject messages", function () {
|
it("shows received chatroom subject messages", function () {
|
||||||
var text = 'Jabber/XMPP Development | RFCs and Extensions: http://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
var text = 'Jabber/XMPP Development | RFCs and Extensions: http://xmpp.org/ | Protocol and XSF discussions: xsf@muc.xmpp.org';
|
||||||
var stanza = Strophe.xmlHtmlNode(
|
var stanza = Strophe.xmlHtmlNode(
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
show_toolbar: converse.show_toolbar,
|
show_toolbar: converse.show_toolbar,
|
||||||
show_textarea: true,
|
show_textarea: true,
|
||||||
title: this.model.get('fullname'),
|
title: this.model.get('fullname'),
|
||||||
|
unread_msgs: __('You have unread messages'),
|
||||||
info_close: __('Close this chat box'),
|
info_close: __('Close this chat box'),
|
||||||
label_personal_message: __('Personal message')
|
label_personal_message: __('Personal message')
|
||||||
}
|
}
|
||||||
@ -333,6 +334,9 @@
|
|||||||
if (converse.windowState === 'blur' || this.model.get('scrolled', true)) {
|
if (converse.windowState === 'blur' || this.model.get('scrolled', true)) {
|
||||||
converse.incrementMsgCounter();
|
converse.incrementMsgCounter();
|
||||||
}
|
}
|
||||||
|
if (this.model.get('scrolled', true)) {
|
||||||
|
this.$el.find('.new-msgs-indicator').removeClass('hidden');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// We remove the "scrolled" flag so that the chat area
|
// We remove the "scrolled" flag so that the chat area
|
||||||
// gets scrolled down. We always want to scroll down
|
// gets scrolled down. We always want to scroll down
|
||||||
@ -688,15 +692,16 @@
|
|||||||
// and the user is scrolled away...
|
// and the user is scrolled away...
|
||||||
// Should probably take a look at incrementMsgCounter
|
// Should probably take a look at incrementMsgCounter
|
||||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||||
var is_at_bottom = this.$content.scrollTop() + this.$content.innerHeight() >= this.$content[0].scrollHeight;
|
var is_at_bottom = this.$content.scrollTop() + this.$content.innerHeight() >= this.$content[0].scrollHeight-10;
|
||||||
if (is_at_bottom) {
|
if (is_at_bottom) {
|
||||||
this.model.set('scrolled', false);
|
this.model.set('scrolled', false);
|
||||||
|
this.$el.find('.new-msgs-indicator').addClass('hidden');
|
||||||
} else {
|
} else {
|
||||||
// We're not at the bottom of the chat area, so we mark
|
// We're not at the bottom of the chat area, so we mark
|
||||||
// that the box is in a scrolled-up state.
|
// that the box is in a scrolled-up state.
|
||||||
this.model.set('scrolled', true);
|
this.model.set('scrolled', true);
|
||||||
}
|
}
|
||||||
}, 50),
|
}, 150),
|
||||||
|
|
||||||
scrollDownMessageHeight: function ($message) {
|
scrollDownMessageHeight: function ($message) {
|
||||||
if (this.$content.is(':visible') && !this.model.get('scrolled')) {
|
if (this.$content.is(':visible') && !this.model.get('scrolled')) {
|
||||||
@ -708,6 +713,7 @@
|
|||||||
scrollDown: function () {
|
scrollDown: function () {
|
||||||
if (this.$content.is(':visible') && !this.model.get('scrolled')) {
|
if (this.$content.is(':visible') && !this.model.get('scrolled')) {
|
||||||
this.$content.scrollTop(this.$content[0].scrollHeight);
|
this.$content.scrollTop(this.$content[0].scrollHeight);
|
||||||
|
this.$el.find('.new-msgs-indicator').addClass('hidden');
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1577,6 +1577,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.setUpXMLLogging = function () {
|
this.setUpXMLLogging = function () {
|
||||||
|
Strophe.log = function (level, msg) {
|
||||||
|
converse.log(msg, level);
|
||||||
|
};
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
this.connection.xmlInput = function (body) { converse.log(body.outerHTML); };
|
this.connection.xmlInput = function (body) { converse.log(body.outerHTML); };
|
||||||
this.connection.xmlOutput = function (body) { converse.log(body.outerHTML); };
|
this.connection.xmlOutput = function (body) { converse.log(body.outerHTML); };
|
||||||
|
@ -93,6 +93,7 @@
|
|||||||
show_toolbar: converse.show_toolbar,
|
show_toolbar: converse.show_toolbar,
|
||||||
show_textarea: false,
|
show_textarea: false,
|
||||||
title: this.model.get('fullname'),
|
title: this.model.get('fullname'),
|
||||||
|
unread_msgs: __('You have unread messages'),
|
||||||
info_close: __('Close this box'),
|
info_close: __('Close this box'),
|
||||||
info_minimize: __('Minimize this box'),
|
info_minimize: __('Minimize this box'),
|
||||||
label_personal_message: ''
|
label_personal_message: ''
|
||||||
|
@ -216,6 +216,7 @@
|
|||||||
this.$('.chatroom-body').empty()
|
this.$('.chatroom-body').empty()
|
||||||
.append(
|
.append(
|
||||||
converse.templates.chatarea({
|
converse.templates.chatarea({
|
||||||
|
'unread_msgs': __('You have unread messages'),
|
||||||
'show_toolbar': converse.show_toolbar,
|
'show_toolbar': converse.show_toolbar,
|
||||||
'label_message': __('Message')
|
'label_message': __('Message')
|
||||||
}))
|
}))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<div class="chat-area">
|
<div class="chat-area">
|
||||||
<div class="chat-content"></div>
|
<div class="chat-content"></div>
|
||||||
|
<div class="new-msgs-indicator hidden">▼ {{ unread_msgs }} ▼</div>
|
||||||
<form class="sendXMPPMessage" action="" method="post">
|
<form class="sendXMPPMessage" action="" method="post">
|
||||||
{[ if (show_toolbar) { ]}
|
{[ if (show_toolbar) { ]}
|
||||||
<ul class="chat-toolbar no-text-select"></ul>
|
<ul class="chat-toolbar no-text-select"></ul>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="chat-body">
|
<div class="chat-body">
|
||||||
<div class="chat-content"></div>
|
<div class="chat-content"></div>
|
||||||
|
<div class="new-msgs-indicator hidden">▼ {{ unread_msgs }} ▼</div>
|
||||||
{[ if (show_textarea) { ]}
|
{[ if (show_textarea) { ]}
|
||||||
<form class="sendXMPPMessage" action="" method="post">
|
<form class="sendXMPPMessage" action="" method="post">
|
||||||
{[ if (show_toolbar) { ]}
|
{[ if (show_toolbar) { ]}
|
||||||
|
@ -55,7 +55,7 @@ require([
|
|||||||
auto_login: true,
|
auto_login: true,
|
||||||
jid: 'dummy@localhost',
|
jid: 'dummy@localhost',
|
||||||
password: 'secret',
|
password: 'secret',
|
||||||
debug: false
|
debug: true
|
||||||
}, function (converse) {
|
}, function (converse) {
|
||||||
window.converse = converse;
|
window.converse = converse;
|
||||||
window.crypto = {
|
window.crypto = {
|
||||||
|
Loading…
Reference in New Issue
Block a user