[IMP] mail: move getScrollableElement to message list model

task-2801089

closes odoo/odoo#87267

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2022-03-28 17:55:16 +02:00
parent e4d125463d
commit 3e249661af
8 changed files with 41 additions and 76 deletions
@@ -69,10 +69,10 @@ export class ChatWindow extends Component {
return;
}
this.chatWindow.threadViewer.saveThreadCacheScrollHeightAsInitial(
this.chatWindow.threadView.messageListView.component.getScrollHeight()
this.chatWindow.threadView.messageListView.getScrollableElement().scrollHeight
);
this.chatWindow.threadViewer.saveThreadCacheScrollPositionsAsInitial(
this.chatWindow.threadView.messageListView.component.getScrollTop()
this.chatWindow.threadView.messageListView.getScrollableElement().scrollTop
);
}
@@ -1,12 +1,11 @@
/** @odoo-module **/
import { useComponentToModel } from '@mail/component_hooks/use_component_to_model';
import { useRefToModel } from '@mail/component_hooks/use_ref_to_model';
import { useUpdate } from '@mail/component_hooks/use_update';
import { registerMessagingComponent } from '@mail/utils/messaging_component';
import { LegacyComponent } from '@web/legacy/legacy_component';
const { useRef } = owl;
export class Chatter extends LegacyComponent {
/**
@@ -16,12 +15,7 @@ export class Chatter extends LegacyComponent {
super.setup();
useUpdate({ func: () => this._update() });
useComponentToModel({ fieldName: 'component', modelName: 'Chatter' });
/**
* Reference of the scroll Panel (Real scroll element). Useful to pass the Scroll element to
* child component to handle proper scrollable element.
*/
this._scrollPanelRef = useRef('scrollPanel');
this.getScrollableElement = this.getScrollableElement.bind(this);
useRefToModel({ fieldName: 'scrollPanelRef', modelName: 'Chatter', refName: 'scrollPanel' });
}
//--------------------------------------------------------------------------
@@ -35,16 +29,6 @@ export class Chatter extends LegacyComponent {
return this.messaging && this.messaging.models['Chatter'].get(this.props.localId);
}
/**
* @returns {Element|undefined} Scrollable Element
*/
getScrollableElement() {
if (!this._scrollPanelRef.el) {
return;
}
return this._scrollPanelRef.el;
}
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -35,7 +35,6 @@
<t t-if="chatter.threadView">
<ThreadView
className="'o_Chatter_thread'"
getScrollableElement="getScrollableElement"
hasScrollAdjust="chatter.hasMessageListScrollAdjust"
localId="chatter.threadView.localId"
/>
@@ -57,9 +57,12 @@ export class MessageList extends Component {
}
_willPatch() {
if (!this.messageListView) {
return;
}
this._willPatchSnapshot = {
scrollHeight: this._getScrollableElement().scrollHeight,
scrollTop: this._getScrollableElement().scrollTop,
scrollHeight: this.messageListView.getScrollableElement().scrollHeight,
scrollTop: this.messageListView.getScrollableElement().scrollTop,
};
}
@@ -127,30 +130,16 @@ export class MessageList extends Component {
this._willPatchSnapshot = undefined;
}
/**
* @returns {integer}
*/
getScrollHeight() {
return this._getScrollableElement().scrollHeight;
}
/**
* @returns {integer}
*/
getScrollTop() {
return this._getScrollableElement().scrollTop;
}
/**
* @param {integer} value
*/
setScrollTop(value) {
const { messageListView } = this._lastRenderedValues();
if (this._getScrollableElement().scrollTop === value) {
if (messageListView.getScrollableElement().scrollTop === value) {
return;
}
messageListView.update({ isLastScrollProgrammatic: true });
this._getScrollableElement().scrollTop = value;
messageListView.getScrollableElement().scrollTop = value;
}
/**
@@ -171,15 +160,16 @@ export class MessageList extends Component {
const {
hasAutoScrollOnMessageReceived,
hasScrollAdjust,
messageListView,
order,
} = this._lastRenderedValues();
if (!this._getScrollableElement() || !hasScrollAdjust) {
if (!messageListView.getScrollableElement() || !hasScrollAdjust) {
return;
}
if (!hasAutoScrollOnMessageReceived) {
if (order === 'desc' && this._willPatchSnapshot) {
const { scrollHeight, scrollTop } = this._willPatchSnapshot;
this.setScrollTop(this._getScrollableElement().scrollHeight - scrollHeight + scrollTop);
this.setScrollTop(messageListView.getScrollableElement().scrollHeight - scrollHeight + scrollTop);
}
return;
}
@@ -192,10 +182,11 @@ export class MessageList extends Component {
_adjustScrollForExtraMessagesAtTheStart() {
const {
hasScrollAdjust,
messageListView,
order,
} = this._lastRenderedValues();
if (
!this._getScrollableElement() ||
!messageListView.getScrollableElement() ||
!hasScrollAdjust ||
!this._willPatchSnapshot ||
order === 'desc'
@@ -203,7 +194,7 @@ export class MessageList extends Component {
return;
}
const { scrollHeight, scrollTop } = this._willPatchSnapshot;
this.setScrollTop(this._getScrollableElement().scrollHeight - scrollHeight + scrollTop);
this.setScrollTop(messageListView.getScrollableElement().scrollHeight - scrollHeight + scrollTop);
}
/**
@@ -212,15 +203,16 @@ export class MessageList extends Component {
_adjustScrollFromModel() {
const {
hasScrollAdjust,
messageListView,
threadCacheInitialScrollHeight,
threadCacheInitialScrollPosition,
} = this._lastRenderedValues();
if (!this._getScrollableElement() || !hasScrollAdjust) {
if (!messageListView.getScrollableElement() || !hasScrollAdjust) {
return;
}
if (
threadCacheInitialScrollPosition !== undefined &&
this._getScrollableElement().scrollHeight === threadCacheInitialScrollHeight
messageListView.getScrollableElement().scrollHeight === threadCacheInitialScrollHeight
) {
this.setScrollTop(threadCacheInitialScrollPosition);
return;
@@ -243,29 +235,18 @@ export class MessageList extends Component {
}
}
/**
* @private
* @returns {Element|undefined} Scrollable Element
*/
_getScrollableElement() {
if (this.props.getScrollableElement) {
return this.props.getScrollableElement();
} else {
return this.root.el;
}
}
/**
* @private
* @returns {boolean}
*/
_isLoadMoreVisible() {
const { messageListView } = this._lastRenderedValues();
const loadMore = this._loadMoreRef.el;
if (!loadMore) {
return false;
}
const loadMoreRect = loadMore.getBoundingClientRect();
const elRect = this._getScrollableElement().getBoundingClientRect();
const elRect = messageListView.getScrollableElement().getBoundingClientRect();
const isInvisible = loadMoreRect.top > elRect.bottom || loadMoreRect.bottom < elRect.top;
return !isInvisible;
}
@@ -276,8 +257,8 @@ export class MessageList extends Component {
* @private
*/
_scrollToEnd() {
const { order } = this._lastRenderedValues();
this.setScrollTop(order === 'asc' ? this._getScrollableElement().scrollHeight - this._getScrollableElement().clientHeight : 0);
const { messageListView, order } = this._lastRenderedValues();
this.setScrollTop(order === 'asc' ? messageListView.getScrollableElement().scrollHeight - messageListView.getScrollableElement().clientHeight : 0);
}
/**
@@ -338,11 +319,11 @@ export class MessageList extends Component {
if (!messageListView || !messageListView.exists()) {
return;
}
if (!this._getScrollableElement()) {
if (!messageListView.getScrollableElement()) {
// could be unmounted in the meantime (due to throttled behavior)
return;
}
const scrollTop = this._getScrollableElement().scrollTop;
const scrollTop = this.messageListView.getScrollableElement().scrollTop;
this.messaging.messagingBus.trigger('o-component-message-list-scrolled', {
orderedMessages,
scrollTop,
@@ -350,9 +331,9 @@ export class MessageList extends Component {
threadViewer: messageListView.threadViewOwner.threadViewer,
});
messageListView.update({
clientHeight: this._getScrollableElement().clientHeight,
scrollHeight: this._getScrollableElement().scrollHeight,
scrollTop: this._getScrollableElement().scrollTop,
clientHeight: messageListView.getScrollableElement().clientHeight,
scrollHeight: messageListView.getScrollableElement().scrollHeight,
scrollTop: messageListView.getScrollableElement().scrollTop,
});
if (!messageListView.isLastScrollProgrammatic) {
// Automatically scroll to new received messages only when the list is
@@ -360,7 +341,7 @@ export class MessageList extends Component {
const hasAutoScrollOnMessageReceived = messageListView.isAtEnd;
messageListView.threadViewOwner.update({ hasAutoScrollOnMessageReceived });
}
messageListView.threadViewOwner.threadViewer.saveThreadCacheScrollHeightAsInitial(this._getScrollableElement().scrollHeight, threadCache);
messageListView.threadViewOwner.threadViewer.saveThreadCacheScrollHeightAsInitial(messageListView.getScrollableElement().scrollHeight, threadCache);
messageListView.threadViewOwner.threadViewer.saveThreadCacheScrollPositionsAsInitial(scrollTop, threadCache);
if (
!messageListView.isLastScrollProgrammatic &&
@@ -44,14 +44,6 @@ Object.assign(ThreadView, {
onFocusin: () => {},
},
props: {
/**
* Function returns the exact scrollable element from the parent
* to manage proper scroll heights which affects the load more messages.
*/
getScrollableElement: {
type: Function,
optional: true,
},
hasComposerCurrentPartnerAvatar: {
type: Boolean,
optional: true,
@@ -20,7 +20,6 @@
<t t-elif="threadView.messageListView">
<MessageList
className="'o_ThreadView_messageList'"
getScrollableElement= "props.getScrollableElement"
hasScrollAdjust="props.hasScrollAdjust"
localId="threadView.messageListView.localId"
/>
+1
View File
@@ -351,6 +351,7 @@ registerModel({
isShowingAttachmentsLoading: attr({
default: false,
}),
scrollPanelRef: attr(),
/**
* Determines the `Thread` that should be displayed by `this`.
*/
@@ -7,6 +7,15 @@ registerModel({
name: 'MessageListView',
identifyingFields: ['threadViewOwner'],
recordMethods: {
/**
* @returns {Element|undefined}
*/
getScrollableElement() {
if (this.threadViewOwner.threadViewer.chatter) {
return this.threadViewOwner.threadViewer.chatter.scrollPanelRef.el;
}
return this.component.root.el;
},
/***
* @private
* @returns {boolean}
@@ -20,7 +29,7 @@ registerModel({
if (this.threadViewOwner.order === 'asc') {
return this.scrollTop >= this.scrollHeight - this.clientHeight - endThreshold;
}
return this.scrollTop <= endThreshold;;
return this.scrollTop <= endThreshold;
},
},
fields: {