[FIX] mail: avoid marking hint as resolved before message list render

This change highlighted issues with the async behavior of `useUpdate`, which
was no longer necessary and therefore reverted.

This in turn highlighted issue with animation of chat window unfolding, making
restoring of scroll position not work as intended due to the message list not
having its whole height available during some time after render. This animation
being minor (and even annoying in some cases) it was decided to remove it.

task-2387729

closes odoo/odoo#61962

X-original-commit: f22c34e7f61f7f8ac5b9ab7f9579cc4e6dd0e334
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2020-11-18 16:28:30 +00:00
parent 315c293b6c
commit 44057dce37
5 changed files with 7 additions and 76 deletions
@@ -1,62 +1,17 @@
odoo.define('mail/static/src/component_hooks/use_update/use_update.js', function (require) {
'use strict';
const { Component } = owl;
const { onMounted, onPatched } = owl.hooks;
const executionQueue = [];
function executeNextInQueue() {
if (executionQueue.length === 0) {
return;
}
const { component, func } = executionQueue.shift();
if (!component.__owl__.isDestroyed) {
func();
}
executeNextInQueue();
}
/**
* @param {Object} param0
* @param {Component} param0.component
* @param {function} param0.func
* @param {integer} param0.priority
*/
async function addFunctionToQueue({ component, func, priority }) {
const index = executionQueue.findIndex(item => item.priority > priority);
const item = { component, func, priority };
if (index === -1) {
executionQueue.push(item);
} else {
executionQueue.splice(index, 0, item);
}
// Timeout to allow all components to register their function before
// executing any of them, to respect all priorities.
await new Promise(resolve => setTimeout(resolve));
executeNextInQueue();
}
/**
* This hook provides support for executing code after update (render or patch).
*
* @param {Object} param0
* @param {function} param0.func the function to execute after the update.
* @param {integer} [param0.priority] determines the execution order of the function
* among the update function of other components. Lower priority is executed
* first. If no priority is given, the function is executed immediately.
*/
function useUpdate({ func, priority }) {
const component = Component.current;
onMounted(onUpdate);
onPatched(onUpdate);
function onUpdate() {
if (priority === undefined) {
func();
return;
}
addFunctionToQueue({ component, func, priority });
}
function useUpdate({ func }) {
onMounted(func);
onPatched(func);
}
return useUpdate;
@@ -91,11 +91,3 @@
.o_ChatWindow_thread .o_ThreadView_messageList {
font-size: 1rem;
}
// ------------------------------------------------------------------
// Animation
// ------------------------------------------------------------------
.o_ChatWindow:not(.o-mobile) {
transition: height 0.3s;
}
@@ -4341,7 +4341,7 @@ QUnit.test('auto-focus composer on opening thread', async function (assert) {
);
});
QUnit.test('mark channel as seen if last message is visible when switching channels when the previous channel had a more recent last message than the current channel', async function (assert) {
QUnit.test('mark channel as seen if last message is visible when switching channels when the previous channel had a more recent last message than the current channel [REQUIRE FOCUS]', async function (assert) {
assert.expect(1);
this.data['mail.channel'].records.push(
@@ -37,10 +37,7 @@ class MessageList extends Component {
},
});
this._getRefs = useRefs();
useUpdate({
func: () => this._update(),
priority: 150, // must be executed after adjust (from thread view)
});
useUpdate({ func: () => this._update() });
/**
* Determine whether the auto-scroll on load is active or not. This
* is useful to disable some times, such as when mounting message list
@@ -540,6 +537,7 @@ class MessageList extends Component {
* @private
*/
_update() {
this.adjustFromComponentHints();
this._checkMostRecentMessageIsVisible();
}
@@ -19,10 +19,7 @@ class ThreadView extends Component {
constructor(...args) {
super(...args);
useStore((...args) => this._useStoreSelector(...args));
useUpdate({
func: () => this._update(),
priority: 100, // must be executed after composer height adjust
});
useUpdate({ func: () => this._update() });
/**
* Reference of the composer. Useful to set focus on composer when
* thread has the focus.
@@ -110,18 +107,7 @@ class ThreadView extends Component {
* @private
*/
_update() {
const messageList = this._messageListRef.comp;
this.trigger('o-rendered');
/**
* Control panel may offset scrolling position of message list due to
* height of buttons. To prevent this, control panel re-render is
* triggered before message list. Correct way should be to adjust
* scroll positions after everything has been rendered, but OWL doesn't
* have such an API for the moment.
*/
if (messageList) {
messageList.adjustFromComponentHints();
}
}
/**