From bbc23764e7e7f09fffd59899988ee9312ecf571c Mon Sep 17 00:00:00 2001 From: JC Brand Date: Wed, 25 May 2016 13:14:12 +0000 Subject: [PATCH] Initial work on keeping track whether the user scrolled so that we don't scroll down while the user is reading messages further up. --- src/converse-chatview.js | 38 +++++++++++++++++++++++++++++++------- src/converse-muc.js | 8 +++++++- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/converse-chatview.js b/src/converse-chatview.js index e020aa8dc..d7f5cc9c3 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -83,6 +83,12 @@ this.model.on('showHelpMessages', this.showHelpMessages, this); this.model.on('sendMessage', this.sendMessage, this); this.render().fetchMessages().insertIntoPage().hide(); + // XXX: adding the event below to the events map above doesn't work. + // The code that gets executed because of that looks like this: + // this.$el.on('scroll', '.chat-content', this.markScrolled.bind(this)); + // Which for some reason doesn't work. + // So working around that fact here: + this.$el.find('.chat-content').on('scroll', this.markScrolled.bind(this)); converse.emit('chatBoxInitialized', this); }, @@ -135,11 +141,8 @@ if (!keep_old) { this.clearStatusNotification(); } - var was_at_bottom = this.$content.scrollTop() + this.$content.innerHeight() >= this.$content[0].scrollHeight; this.$content.append($('
').text(message)); - if (was_at_bottom) { - this.scrollDown(); - } + this.scrollDown(); }, addSpinner: function () { @@ -326,7 +329,7 @@ handleTextMessage: function (message) { this.showMessage(_.clone(message.attributes)); - if ((message.get('sender') !== 'me') && (converse.windowState === 'blur')) { + if ((message.get('sender') !== 'me') && (converse.windowState === 'blur') || this.model.get('scrolled', true)) { converse.incrementMsgCounter(); } if (this.shouldShowOnTextMessage()) { @@ -666,15 +669,36 @@ return this; }, + markScrolled: _.debounce(function (ev) { + /* Called when the chat content is scrolled up or down. + * We want to record when the user has scrolled away from + * the bottom, so that we don't automatically scroll away + * from what the user is reading when new messages are + * received. + */ + // TODO: need to indicate when new messages are received + // and the user is scrolled away... + // Should probably take a look at incrementMsgCounter + if (ev && ev.preventDefault) { ev.preventDefault(); } + var is_at_bottom = this.$content.scrollTop() + this.$content.innerHeight() >= this.$content[0].scrollHeight; + if (is_at_bottom) { + this.model.set('scrolled', false); + } else { + // We're not at the bottom of the chat area, so we mark + // that the box is in a scrolled-up state. + this.model.set('scrolled', true); + } + }, 50), + scrollDownMessageHeight: function ($message) { - if (this.$content.is(':visible')) { + if (this.$content.is(':visible') && !this.model.get('scrolled')) { this.$content.scrollTop(this.$content.scrollTop() + $message[0].scrollHeight); } return this; }, scrollDown: function () { - if (this.$content.is(':visible')) { + if (this.$content.is(':visible') && !this.model.get('scrolled')) { this.$content.scrollTop(this.$content[0].scrollHeight); } return this; diff --git a/src/converse-muc.js b/src/converse-muc.js index 7a634df65..2d5da7c80 100755 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -175,7 +175,7 @@ 'click .toggle-clear': 'clearChatRoomMessages', 'click .toggle-call': 'toggleCall', 'click .toggle-occupants a': 'toggleOccupants', - 'keypress textarea.chat-textarea': 'keyPressed', + 'keypress textarea.chat-textarea': 'keyPressed' }, initialize: function () { @@ -194,6 +194,12 @@ this.join(null, {'maxstanzas': converse.muc_history_max_stanzas}); this.fetchMessages(); this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el); + // XXX: adding the event below to the events map above doesn't work. + // The code that gets executed because of that looks like this: + // this.$el.on('scroll', '.chat-content', this.markScrolled.bind(this)); + // Which for some reason doesn't work. + // So working around that fact here: + this.$el.find('.chat-content').on('scroll', this.markScrolled.bind(this)); converse.emit('chatRoomOpened', this); },