Improve automatic scrolling behaviour when new messages arrive

When the chat messages are shown from newest to oldest and a new message
arrives the list is automatically scrolled to keep the current visible
messages at the same place, except if the list was at the top, in which
case no scrolling is made and the new message appears.

When the chat messages are shown from oldest to newest and a new message
arrives the list is automatically scrolled to show the new message,
except if the list was not at the bottom in which case no scrolling is
made and the current visible messages are kept at the same place.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2018-01-09 14:52:41 +01:00
Родитель 2c7ef423cf
Коммит 3c0587f31c
2 изменённых файлов: 40 добавлений и 0 удалений

Просмотреть файл

@ -172,6 +172,11 @@
#app-content-wrapper #commentsTabView .comments {
overflow-y: auto;
/* Needed for proper calculation of comment positions in the scrolling
container (as otherwise the comment position is calculated with respect
to the closest ancestor with a relative position) */
position: relative;
padding-left: 15px;
padding-right: 15px;
}
@ -1001,6 +1006,11 @@ video {
#app-sidebar .comments {
overflow-y: auto;
/* Needed for proper calculation of comment positions in the scrolling
container (as otherwise the comment position is calculated with respect
to the closest ancestor with a relative position) */
position: relative;
}
/**

Просмотреть файл

@ -166,6 +166,23 @@
_onAddModel: function(model, collection, options) {
this.$el.find('.emptycontent').toggleClass('hidden', true);
var scrollToNew = false;
var scrollBack = false;
if (this._oldestOnTopLayout) {
var $newestComment = this.$container.children('.comment').last();
var scrollToNew = $newestComment.length > 0 && $newestComment.position().top < this.$container.outerHeight(true);
} else {
var $firstComment = this.$container.children('.comment').first();
var scrollBack = $firstComment.length > 0 && ($firstComment.position().top + $firstComment.outerHeight()) < 0;
}
if (scrollBack) {
var $firstVisibleComment = this.$container.children('.comment').filter(function() {
return $(this).position().top > 0;
}).first();
var firstVisibleCommentTop = Math.round($firstVisibleComment.position().top);
}
var $el = $(this.commentTemplate(this._formatItem(model)));
if (!_.isUndefined(options.at) && collection.length > 1) {
this.$container.find('li').eq(options.at).before($el);
@ -207,6 +224,19 @@
this._lastAddedMessageModel = model;
this._postRenderItem($el);
if (scrollToNew) {
var newestCommentHiddenHeight = ($newestComment.position().top + $newestComment.outerHeight(true)) - this.$container.outerHeight(true);
this.$container.scrollTop(this.$container.scrollTop() + newestCommentHiddenHeight + $el.outerHeight(true));
} else if (scrollBack) {
var newFirstVisibleCommentTop = Math.round($firstVisibleComment.position().top);
// It is not enough to just add the outer height of the added
// element, as the height of other elements could change too
// (for example, if the previous last message was grouped with
// the new one).
this.$container.scrollTop(this.$container.scrollTop() + (newFirstVisibleCommentTop - firstVisibleCommentTop));
}
},
_modelsHaveSameActor: function(model1, model2) {