[IMP] mail: Discuss: load older messages automatically

After this rev., in Discuss, messages are automatically loaded when
the user scrolls to the top of the channel.

Task 33958

Co-authored-by: Aaron Bohy <aab@odoo.com>
This commit is contained in:
dbh
2018-03-30 15:30:37 +02:00
committed by Aaron Bohy
co-authored by Aaron Bohy
parent c5c2b4855b
commit ea97fa3ac6
4 changed files with 117 additions and 4 deletions
+26 -2
View File
@@ -184,6 +184,11 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
.then(function () {
self._startListening();
self.thread.$el.on("scroll", null, _.debounce(function () {
if (self.thread.get_scrolltop() < 20 &&
!self.thread.$('.o_mail_no_content').length &&
!self.call('chat_manager', 'isAllHistoryLoaded', self.channel, self.domain)) {
self._loadMoreMessages();
}
if (self.thread.is_at_bottom()) {
self.call('chat_manager', 'markChannelAsSeen', self.channel);
}
@@ -218,6 +223,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
if (this.channel) {
this.thread.scroll_to({offset: this.channelsScrolltop[this.channel.id]});
}
this._loadEnoughMessages();
},
/**
* @override
@@ -243,6 +249,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
}).then(function (messages) {
self.thread.render(messages, self._getThreadRenderingOptions(messages));
self._updateButtonStatus(messages.length === 0);
return self._loadEnoughMessages();
});
},
/**
@@ -274,6 +281,23 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
display_reply_icon: true,
};
},
/**
* Ensures that enough messages have been loaded to fill the entire screen
* (this is particularily important because remaining messages can only be
* loaded when scrolling to the top, so they can't be loaded if there is no
* scrollbar)
*
* @returns {Deferred} resolved when there are enough messages to fill the
* screen, or when there is no more message to fetch
*/
_loadEnoughMessages: function () {
var loadMoreMessages = this.thread.el.clientHeight &&
this.thread.el.clientHeight === this.thread.el.scrollHeight &&
!this.call('chat_manager', 'isAllHistoryLoaded', this.channel, this.domain);
if (loadMoreMessages) {
return this._loadMoreMessages().then(this._loadEnoughMessages.bind(this));
}
},
/**
* Load more messages for the current thread
*
@@ -429,7 +453,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
*/
_renderThread: function () {
var self = this;
this.thread = new ChatThread(this, {display_help: true});
this.thread = new ChatThread(this, {display_help: true, loadMoreOnScroll: true});
this.thread.on('redirect', this, function (resModel, resID) {
self.call('chat_manager', 'redirect', resModel, resID, self._setChannel.bind(self));
@@ -615,7 +639,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
*/
_unselectMessage: function () {
this.basicComposer.do_toggle(this.channel.type !== 'static' && !this.channel.mass_mailing);
this.extendedComposer.do_toggle(this.channel.type !== 'static' && this.channel.mass_mailing);
this.extendedComposer.do_toggle(this.channel.type !== 'static' && !!this.channel.mass_mailing);
if (!config.device.touch) {
var composer = this.channel.mass_mailing ? this.extendedComposer : this.basicComposer;
+2
View File
@@ -83,6 +83,7 @@ var Thread = Widget.extend({
squash_close_messages: true,
display_email_icon: true,
display_reply_icon: false,
loadMoreOnScroll: false,
});
this.disabledOptions = {
display_order: this.enabledOptions.display_order,
@@ -93,6 +94,7 @@ var Thread = Widget.extend({
squash_close_messages: false,
display_email_icon: false,
display_reply_icon: false,
loadMoreOnScroll: this.enabledOptions.loadMoreOnScroll,
};
this.expanded_msg_ids = [];
this.selected_id = null;
+7 -2
View File
@@ -332,8 +332,13 @@
</t>
<t t-name="mail.ChatThread.LoadMore">
<div t-if="!all_messages_loaded" class="o_thread_show_more">
<button class="btn btn-sm btn-link">-------- Show older messages --------</button>
<div class="o_thread_show_more">
<t t-if="options.loadMoreOnScroll">
<span><i class="fa fa-spinner fa-spin"/> Loading older messages... </span>
</t>
<t t-else="">
<button class="btn btn-sm btn-link">-------- Show older messages --------</button>
</t>
</div>
</t>
</templates>
+82
View File
@@ -293,5 +293,87 @@ QUnit.test('no crash focusout emoji button', function (assert) {
});
});
QUnit.test('older messages are loaded on scroll', function (assert) {
assert.expect(4);
var done = assert.async();
// remove throttling
testUtils.patch(BasicComposer, {MENTION_THROTTLE: 0});
testUtils.patch(ChatManager, {CHANNEL_SEEN_THROTTLE: 0});
this.data.initMessaging = {
channel_slots: {
channel_channel: [{
id: 1,
channel_type: "channel",
name: "general",
static: true,
}],
},
};
var limit;
var loadDef = $.Deferred();
var loadedMessages;
var msgData = [];
for (var i = 0; i < 35; i++) {
msgData.push({
author_id: ['1', 'Me'],
body: '<p>test ' + i + '</p>',
channel_ids: [1],
id: i,
});
}
msgData.reverse();
createDiscuss({
context: {},
data: this.data,
params: {},
services: [ChatManager, createBusService()],
mockRPC: function (route, args) {
if (args.method === 'message_fetch') {
limit = args.kwargs.limit;
loadedMessages += limit;
var message = msgData.slice(0, loadedMessages);
if (loadedMessages >= msgData.length) {
loadDef.resolve();
}
return $.when(message);
}
return this._super.apply(this, arguments);
},
}).then(function (discuss) {
var $general = discuss.$('.o_mail_chat_channel_item[data-channel-id=1]');
assert.strictEqual($general.length, 1,
"should have a channel item with id 1");
// switch to 'general'
loadedMessages = 0;
$general.click();
assert.ok(limit < 35, "there should be more messages than the limit");
assert.strictEqual(discuss.$('.o_thread_message').length, limit,
"should display the 'limit' first messages");
// simulate a scroll to top to load more messages
discuss.$('.o_mail_thread').scrollTop(0);
loadDef
.then(concurrency.delay.bind(concurrency, 0))
.then(function () {
assert.strictEqual(discuss.$('.o_thread_message').length, 35,
"all messages should now be loaded");
// restore throttling
testUtils.unpatch(BasicComposer);
testUtils.unpatch(ChatManager);
discuss.destroy();
done();
});
});
});
});
});