summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/models/thread_view/thread_viewer.js
diff options
context:
space:
mode:
authorXavier Dubuc <xdu@odoo.com>2020-09-03 16:24:19 +0000
committerSébastien Theys <seb@odoo.com>2020-09-04 14:59:01 +0000
commit8d3413ff647de8d98c6858062dd07dde4160af95 (patch)
tree3dc134e83c874d5c7f7bf739f13a88ab986ddb1b /addons/mail/static/src/models/thread_view/thread_viewer.js
parenta5ab687be4e7890262ce9429e18dd011021513d5 (diff)
[FIX] mail, sms, snailmail: prevent message_fetch for hidden threads
Automatically load messages from a thread cache only if the thread cache is used in at least one thread view. Ensure thread viewer don't keep thread view records alive when they are not displayed. This change is particularly important for performance, to avoid spamming RPC at init if many threads are opened in chat windows. task-2310623 closes odoo/odoo#57061 X-original-commit: dd6981c7812134e0588f80a157eaba45512cd68e Related: odoo/enterprise#12936 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Diffstat (limited to 'addons/mail/static/src/models/thread_view/thread_viewer.js')
-rw-r--r--addons/mail/static/src/models/thread_view/thread_viewer.js257
1 files changed, 257 insertions, 0 deletions
diff --git a/addons/mail/static/src/models/thread_view/thread_viewer.js b/addons/mail/static/src/models/thread_view/thread_viewer.js
new file mode 100644
index 00000000000..da546338ca3
--- /dev/null
+++ b/addons/mail/static/src/models/thread_view/thread_viewer.js
@@ -0,0 +1,257 @@
+odoo.define('mail/static/src/models/thread_viewer/thread_viewer.js', function (require) {
+'use strict';
+
+const { registerNewModel } = require('mail/static/src/model/model_core.js');
+const { attr, many2one, one2one } = require('mail/static/src/model/model_field.js');
+
+function factory(dependencies) {
+
+ class ThreadViewer extends dependencies['mail.model'] {
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ /**
+ * @param {string} scrollTop
+ */
+ saveThreadCacheScrollPositionsAsInitial(scrollTop) {
+ if (!this.threadCache) {
+ return;
+ }
+ this.update({
+ threadCacheInitialScrollPositions: Object.assign({}, this.threadCacheInitialScrollPositions, {
+ [this.threadCache.localId]: scrollTop,
+ }),
+ });
+ }
+
+ //----------------------------------------------------------------------
+ // Private
+ //----------------------------------------------------------------------
+
+ /**
+ * @private
+ * @returns {boolean}
+ */
+ _computeHasThreadView() {
+ if (this.chatter) {
+ return this.chatter.hasThreadView;
+ }
+ if (this.chatWindow) {
+ return this.chatWindow.hasThreadView;
+ }
+ if (this.discuss) {
+ return this.discuss.hasThreadView;
+ }
+ return this.hasThreadView;
+ }
+
+ /**
+ * @private
+ * @returns {string}
+ */
+ _computeStringifiedDomain() {
+ if (this.chatter) {
+ return '[]';
+ }
+ if (this.chatWindow) {
+ return '[]';
+ }
+ if (this.discuss) {
+ return this.discuss.stringifiedDomain;
+ }
+ return this.stringifiedDomain;
+ }
+
+ /**
+ * @private
+ * @returns {mail.thread|undefined}
+ */
+ _computeThread() {
+ if (this.chatter) {
+ if (!this.chatter.thread) {
+ return [['unlink']];
+ }
+ return [['link', this.chatter.thread]];
+ }
+ if (this.chatWindow) {
+ if (!this.chatWindow.thread) {
+ return [['unlink']];
+ }
+ return [['link', this.chatWindow.thread]];
+ }
+ if (this.discuss) {
+ if (!this.discuss.thread) {
+ return [['unlink']];
+ }
+ return [['link', this.discuss.thread]];
+ }
+ return [];
+ }
+
+ /**
+ * @private
+ * @returns {mail.thread_cache|undefined}
+ */
+ _computeThreadCache() {
+ if (!this.thread) {
+ return [['unlink']];
+ }
+ return [['link', this.thread.cache(this.stringifiedDomain)]];
+ }
+
+ /**
+ * @private
+ * @returns {mail.thread_viewer|undefined}
+ */
+ _computeThreadView() {
+ if (!this.hasThreadView) {
+ return [['unlink']];
+ }
+ if (this.threadView) {
+ return [];
+ }
+ return [['create']];
+ }
+
+ }
+
+ ThreadViewer.fields = {
+ /**
+ * States the `mail.chatter` managing `this`. This field is computed
+ * through the inverse relation and should be considered read-only.
+ */
+ chatter: one2one('mail.chatter', {
+ inverse: 'threadViewer',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ chatterHasThreadView: attr({
+ related: 'chatter.hasThreadView',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ chatterThread: many2one('mail.thread', {
+ related: 'chatter.thread',
+ }),
+ /**
+ * States the `mail.chat_window` managing `this`. This field is computed
+ * through the inverse relation and should be considered read-only.
+ */
+ chatWindow: one2one('mail.chat_window', {
+ inverse: 'threadViewer',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ chatWindowHasThreadView: attr({
+ related: 'chatWindow.hasThreadView',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ chatWindowThread: many2one('mail.thread', {
+ related: 'chatWindow.thread',
+ }),
+ /**
+ * States the `mail.discuss` managing `this`. This field is computed
+ * through the inverse relation and should be considered read-only.
+ */
+ discuss: one2one('mail.discuss', {
+ inverse: 'threadViewer',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ discussHasThreadView: attr({
+ related: 'discuss.hasThreadView',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ discussStringifiedDomain: attr({
+ related: 'discuss.stringifiedDomain',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ discussThread: many2one('mail.thread', {
+ related: 'discuss.thread',
+ }),
+ /**
+ * Determines whether `this.thread` should be displayed.
+ */
+ hasThreadView: attr({
+ compute: '_computeHasThreadView',
+ default: false,
+ dependencies: [
+ 'chatterHasThreadView',
+ 'chatWindowHasThreadView',
+ 'discussHasThreadView',
+ ],
+ }),
+ /**
+ * Determines the domain to apply when fetching messages for `this.thread`.
+ */
+ stringifiedDomain: attr({
+ compute: '_computeStringifiedDomain',
+ default: '[]',
+ dependencies: [
+ 'discussStringifiedDomain',
+ ],
+ }),
+ /**
+ * Determines the `mail.thread` that should be displayed by `this`.
+ */
+ thread: many2one('mail.thread', {
+ compute: '_computeThread',
+ dependencies: [
+ 'chatterThread',
+ 'chatWindowThread',
+ 'discussThread',
+ ],
+ }),
+ /**
+ * States the `mail.thread_cache` that should be displayed by `this`.
+ */
+ threadCache: many2one('mail.thread_cache', {
+ compute: '_computeThreadCache',
+ dependencies: [
+ 'stringifiedDomain',
+ 'thread',
+ ],
+ }),
+ /**
+ * Determines the 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: {},
+ }),
+ /**
+ * States the `mail.thread_view` currently displayed and managed by `this`.
+ */
+ threadView: one2one('mail.thread_view', {
+ compute: '_computeThreadView',
+ dependencies: [
+ 'hasThreadView',
+ ],
+ inverse: 'threadViewer',
+ isCausal: true,
+ }),
+ };
+
+ ThreadViewer.modelName = 'mail.thread_viewer';
+
+ return ThreadViewer;
+}
+
+registerNewModel('mail.thread_viewer', factory);
+
+});