summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/models/thread_view/thread_view.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/mail/static/src/models/thread_view/thread_view.js')
-rw-r--r--addons/mail/static/src/models/thread_view/thread_view.js200
1 files changed, 99 insertions, 101 deletions
diff --git a/addons/mail/static/src/models/thread_view/thread_view.js b/addons/mail/static/src/models/thread_view/thread_view.js
index f0075314561..d7ea1508067 100644
--- a/addons/mail/static/src/models/thread_view/thread_view.js
+++ b/addons/mail/static/src/models/thread_view/thread_view.js
@@ -13,7 +13,7 @@ function factory(dependencies) {
* @override
*/
_willDelete() {
- this._stopLoading();
+ this.env.browser.clearTimeout(this._loaderTimeout);
return super._willDelete(...arguments);
}
@@ -41,16 +41,6 @@ function factory(dependencies) {
}
/**
- * @param {mail.thread_cache} threadCache
- */
- handleThreadCacheLoaded(threadCache) {
- if (threadCache !== this.threadCache) {
- return;
- }
- this._stopLoading();
- }
-
- /**
* @param {Object} hint
*/
markComponentHintProcessed(hint) {
@@ -77,33 +67,19 @@ function factory(dependencies) {
}
}
- /**
- * @param {string} scrollTop
- */
- saveThreadCacheScrollPositionsAsInitial(scrollTop) {
- if (!this.threadCache) {
- return;
- }
- this.update({
- threadCacheInitialScrollPositions: Object.assign({}, this.threadCacheInitialScrollPositions, {
- [this.threadCache.localId]: scrollTop,
- }),
- });
- }
-
//----------------------------------------------------------------------
// Private
//----------------------------------------------------------------------
/**
* @private
- * @returns {mail.thread_cache|undefined}
+ * @returns {integer|undefined}
*/
- _computeThreadCache() {
- if (!this.thread) {
- return [];
+ _computeThreadCacheInitialScrollPosition() {
+ if (!this.threadCache) {
+ return;
}
- return [['link', this.thread.cache(this.stringifiedDomain)]];
+ return this.threadCacheInitialScrollPositions[this.threadCache.localId];
}
/**
@@ -131,75 +107,37 @@ function factory(dependencies) {
/**
* @private
- * @returns {integer|undefined}
- */
- _computeThreadCacheInitialScrollPosition() {
- if (!this.threadCache) {
- return undefined;
- }
- return this.threadCacheInitialScrollPositions[this.threadCache.localId];
- }
-
- /**
- * @private
*/
- _prepareLoading() {
- this._isPreparingLoading = true;
- this._loaderTimeout = setTimeout(() => {
- this.isShowingLoading = true;
- this._isPreparingLoading = false;
- }, 400);
+ _onThreadCacheChanged() {
+ this.addComponentHint('change-of-thread-cache');
}
/**
* @private
*/
- _stopLoading() {
- clearTimeout(this._loaderTimeout);
- this._loaderTimeout = null;
- this.isShowingLoading = false;
- this._isPreparingLoading = false;
- }
-
- /**
- * @override
- */
- _updateAfter(previous) {
- if (this.thread && this.thread !== previous.thread) {
- this._stopLoading();
- if (!this.threadCache.isLoaded && !this.threadCache.isLoading) {
- this.threadCache.loadMessages();
+ _onThreadCacheIsLoadingChanged() {
+ if (this.threadCache && this.threadCache.isLoading) {
+ if (!this.isLoading && !this.isPreparingLoading) {
+ this.update({ isPreparingLoading: true });
+ this.async(() =>
+ new Promise(resolve => {
+ this._loaderTimeout = this.env.browser.setTimeout(resolve, 400);
+ }
+ )).then(() => {
+ const isLoading = this.threadCache
+ ? this.threadCache.isLoading
+ : false;
+ this.update({ isLoading, isPreparingLoading: false });
+ });
}
+ return;
}
- if (this.threadCache !== previous.threadCache) {
- this._stopLoading();
- this.addComponentHint('change-of-thread-cache');
- }
-
- if (
- this.thread && this.threadCache && this.threadCache.isLoading &&
- !this.isShowingLoading && !this._isPreparingLoading
- ) {
- this._prepareLoading();
- }
- }
-
- /**
- * @override
- */
- _updateBefore() {
- return {
- thread: this.thread,
- threadCache: this.threadCache,
- };
+ this.env.browser.clearTimeout(this._loaderTimeout);
+ this.update({ isLoading: false, isPreparingLoading: false });
}
-
}
ThreadView.fields = {
- chatWindow: one2one('mail.chat_window', {
- inverse: 'threadView',
- }),
checkedMessages: many2many('mail.message', {
related: 'threadCache.checkedMessages',
}),
@@ -230,6 +168,31 @@ function factory(dependencies) {
hasComposerFocus: attr({
related: 'composer.hasFocus',
}),
+ /**
+ * States whether `this.threadCache` is currently loading messages.
+ *
+ * This field is related to `this.threadCache.isLoading` but with a
+ * delay on its update to avoid flickering on the UI.
+ *
+ * It is computed through `_onThreadCacheIsLoadingChanged` and it should
+ * otherwise be considered read-only.
+ */
+ isLoading: attr({
+ default: false,
+ }),
+ /**
+ * States whether `this` is aware of `this.threadCache` currently
+ * loading messages, but `this` is not yet ready to display that loading
+ * on the UI.
+ *
+ * This field is computed through `_onThreadCacheIsLoadingChanged` and
+ * it should otherwise be considered read-only.
+ *
+ * @see `this.isLoading`
+ */
+ isPreparingLoading: attr({
+ default: false,
+ }),
lastMessage: many2one('mail.message', {
related: 'thread.lastMessage',
}),
@@ -241,19 +204,48 @@ function factory(dependencies) {
messages: many2many('mail.message', {
related: 'threadCache.messages',
}),
+ /**
+ * Not a real field, used to trigger `_onThreadCacheChanged` when one of
+ * the dependencies changes.
+ */
+ onThreadCacheChanged: attr({
+ compute: '_onThreadCacheChanged',
+ dependencies: [
+ 'threadCache'
+ ],
+ }),
+ /**
+ * Not a real field, used to trigger `_onThreadCacheIsLoadingChanged`
+ * when one of the dependencies changes.
+ *
+ * @see `this.isLoading`
+ */
+ onThreadCacheIsLoadingChanged: attr({
+ compute: '_onThreadCacheIsLoadingChanged',
+ dependencies: [
+ 'threadCache',
+ 'threadCacheIsLoading',
+ ],
+ }),
+ /**
+ * Determines the domain to apply when fetching messages for `this.thread`.
+ */
stringifiedDomain: attr({
- default: '[]',
+ related: 'threadViewer.stringifiedDomain',
}),
+ /**
+ * Determines the `mail.thread` currently displayed by `this`.
+ */
thread: many2one('mail.thread', {
inverse: 'threadViews',
+ related: 'threadViewer.thread',
}),
+ /**
+ * States the `mail.thread_cache` currently displayed by `this`.
+ */
threadCache: many2one('mail.thread_cache', {
- compute: '_computeThreadCache',
- dependencies: [
- 'stringifiedDomain',
- 'thread',
- 'threadCaches',
- ],
+ inverse: 'threadViews',
+ related: 'threadViewer.threadCache',
}),
threadCacheInitialScrollPosition: attr({
compute: '_computeThreadCacheInitialScrollPosition',
@@ -263,17 +255,17 @@ function factory(dependencies) {
],
}),
/**
+ * Serves as compute dependency.
+ */
+ threadCacheIsLoading: attr({
+ related: 'threadCache.isLoading',
+ }),
+ /**
* List of saved initial scroll positions of thread caches.
- * Useful to restore scroll position on changing back to this
- * thread cache. Note that this is only applied when opening
- * the thread cache, because scroll position may change fast so
- * save is already throttled
*/
threadCacheInitialScrollPositions: attr({
default: {},
- }),
- threadCaches: many2many('mail.thread_cache', {
- related: 'thread.caches',
+ related: 'threadViewer.threadCacheInitialScrollPositions',
}),
/**
* Not a real field, used to trigger `thread.markAsSeen` when one of
@@ -288,6 +280,12 @@ function factory(dependencies) {
'threadCache',
],
}),
+ /**
+ * Determines the `mail.thread_viewer` currently managing `this`.
+ */
+ threadViewer: one2one('mail.thread_viewer', {
+ inverse: 'threadView',
+ }),
uncheckedMessages: many2many('mail.message', {
related: 'threadCache.uncheckedMessages',
}),