summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/js/models/utils
diff options
context:
space:
mode:
authorAlexandre Kühn <aku@odoo.com>2018-12-05 14:35:26 +0000
committerAlexandre Kühn <aku@odoo.com>2018-12-06 16:18:09 +0000
commit15bbadb69b1b26404a614736c3cde7980d3c1dfd (patch)
tree81dd1957900c612d5a06830f172b685b1326f11e /addons/mail/static/src/js/models/utils
parent50dfa865ea32c88d55e7eb0fce6a6ae978c9c3b4 (diff)
[REF] im_livechat, mail, website_livechat: clean mail model folder
The utility classes `Timer`, `Timers` and `CCThrottleFunction` were only used by the feature 'is typing...', thus all those files were in the same folder. This commit moves the utility classes in a dedicated folder, and introduces a folder for thread mixins, in preparation for future features on threads that will be implemented as mixins.
Diffstat (limited to 'addons/mail/static/src/js/models/utils')
-rw-r--r--addons/mail/static/src/js/models/utils/cc_throttle_function.js181
-rw-r--r--addons/mail/static/src/js/models/utils/timer.js69
-rw-r--r--addons/mail/static/src/js/models/utils/timers.js82
3 files changed, 332 insertions, 0 deletions
diff --git a/addons/mail/static/src/js/models/utils/cc_throttle_function.js b/addons/mail/static/src/js/models/utils/cc_throttle_function.js
new file mode 100644
index 00000000000..b4b87087e6d
--- /dev/null
+++ b/addons/mail/static/src/js/models/utils/cc_throttle_function.js
@@ -0,0 +1,181 @@
+odoo.define('mail.model.CCThrottleFunctionObject', function (require) {
+"use strict";
+
+var Class = require('web.Class');
+
+/**
+ * This object models the behaviour of the clearable and cancellable (CC)
+ * throttle version of a provided function.
+ */
+var CCThrottleFunctionObject = Class.extend({
+
+ /**
+ * @param {Object} params
+ * @param {integer} params.duration duration of the 'cooldown' phase, i.e.
+ * the minimum duration between the most recent function call that has
+ * been made and the following function call.
+ * @param {function} params.func provided function for making the CC
+ * throttled version.
+ */
+ init: function (params) {
+ this._arguments = undefined;
+ this._cooldownTimeout = undefined;
+ this._duration = params.duration;
+ this._func = params.func;
+ this._shouldCallFunctionAfterCD = false;
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * Cancel any buffered function call, but keep the cooldown phase running.
+ */
+ cancel: function () {
+ this._arguments = undefined;
+ this._shouldCallFunctionAfterCD = false;
+ },
+ /**
+ * Clear the internal throttle timer, so that the following function call
+ * is immediate. For instance, if there is a cooldown stage, it is aborted.
+ */
+ clear: function () {
+ if (this._cooldownTimeout) {
+ clearTimeout(this._cooldownTimeout);
+ this._onCooldownTimeout();
+ }
+ },
+ /**
+ * Called when there is a call to the function. This function is throttled,
+ * so the time it is called depends on whether the "cooldown stage" occurs
+ * or not:
+ *
+ * - no cooldown stage: function is called immediately, and it starts
+ * the cooldown stage when successful.
+ * - in cooldown stage: function is called when the cooldown stage has
+ * ended from timeout.
+ *
+ * Note that after the cooldown stage, only the last attempted function
+ * call will be considered.
+ */
+ do: function () {
+ this._arguments = Array.prototype.slice.call(arguments);
+ if (this._cooldownTimeout === undefined) {
+ this._callFunction();
+ } else {
+ this._shouldCallFunctionAfterCD = true;
+ }
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Immediately calls the function with arguments of last buffered function
+ * call. It initiates the cooldown stage after this function call.
+ *
+ * @private
+ */
+ _callFunction: function () {
+ this._func.apply(null, this._arguments);
+ this._cooldown();
+ },
+ /**
+ * Called when the function has been successfully called. The following
+ * calls to the function with this object should suffer a "cooldown stage",
+ * which prevents the function from being called until this stage has ended.
+ *
+ * @private
+ */
+ _cooldown: function () {
+ this.cancel();
+ this._cooldownTimeout = setTimeout(
+ this._onCooldownTimeout.bind(this),
+ this._duration
+ );
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Called when the cooldown stage ended from timeout. Calls the function if
+ * a function call was buffered.
+ *
+ * @private
+ */
+ _onCooldownTimeout: function () {
+ if (this._shouldCallFunctionAfterCD) {
+ this._callFunction();
+ } else {
+ this._cooldownTimeout = undefined;
+ }
+ },
+});
+
+return CCThrottleFunctionObject;
+
+});
+
+
+odoo.define('mail.model.CCThrottleFunction', function (require) {
+"use strict";
+
+var CCThrottleFunctionObject = require('mail.model.CCThrottleFunctionObject');
+
+/**
+ * A function that creates a cancellable and clearable (CC) throttle version
+ * of a provided function.
+ *
+ * This throttle mechanism allows calling a function at most once during a
+ * certain period:
+ *
+ * - When a function call is made, it enters a 'cooldown' phase, in which any
+ * attempt to call the function is buffered until the cooldown phase ends.
+ * - At most 1 function call can be buffered during the cooldown phase, and the
+ * latest one in this phase will be considered at its end.
+ * - When a cooldown phase ends, any buffered function call will be performed
+ * and another cooldown phase will follow up.
+ *
+ * This throttle version has the following interesting properties:
+ *
+ * - cancellable: it allows removing a buffered function call during the
+ * cooldown phase, but it keeps the cooldown phase running.
+ * - clearable: it allows to clear the internal clock of the throttled function,
+ * so that any cooldown phase is immediately ending.
+ *
+ * @param {Object} params
+ * @param {integer} params.duration a duration for the throttled behaviour,
+ * in milli-seconds.
+ * @param {function} params.func the function to throttle
+ * @returns {function} the cancellable and clearable throttle version of the
+ * provided function in argument.
+ */
+var CCThrottleFunction = function (params) {
+ var duration = params.duration;
+ var func = params.func;
+
+ var throttleFunctionObject = new CCThrottleFunctionObject({
+ duration: duration,
+ func: func,
+ });
+
+ var callable = function () {
+ return throttleFunctionObject.do.apply(throttleFunctionObject, arguments);
+ };
+ callable.cancel = function () {
+ throttleFunctionObject.cancel();
+ };
+ callable.clear = function () {
+ throttleFunctionObject.clear();
+ };
+
+ return callable;
+};
+
+return CCThrottleFunction;
+
+});
diff --git a/addons/mail/static/src/js/models/utils/timer.js b/addons/mail/static/src/js/models/utils/timer.js
new file mode 100644
index 00000000000..a3236fd1a16
--- /dev/null
+++ b/addons/mail/static/src/js/models/utils/timer.js
@@ -0,0 +1,69 @@
+odoo.define('mail.model.Timer', function (require) {
+"use strict";
+
+var Class = require('web.Class');
+
+/**
+ * This class creates a timer which, when times out, calls a function.
+ */
+var Timer = Class.extend({
+
+ /**
+ * Instantiate a new timer. Note that the timer is not started on
+ * initialization (@see start method).
+ *
+ * @param {Object} params
+ * @param {integer} params.duration duration of timer before timeout in
+ * milli-seconds.
+ * @param {function} params.onTimeout function that is called when the
+ * timer times out.
+ */
+ init: function (params) {
+ this._duration = params.duration;
+ this._timeout = undefined;
+ this._timeoutCallback = params.onTimeout;
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * Clears the countdown of the timer.
+ */
+ clear: function () {
+ clearTimeout(this._timeout);
+ },
+ /**
+ * Resets the timer, i.e. resets its duration.
+ */
+ reset: function () {
+ this.clear();
+ this.start();
+ },
+ /**
+ * Starts the timer, i.e. after a certain duration, it times out and calls
+ * a function back.
+ */
+ start: function () {
+ this._timeout = setTimeout(this._onTimeout.bind(this), this._duration);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handler
+ //--------------------------------------------------------------------------
+
+ /**
+ * Called when the timer times out, calls back a function on timeout.
+ *
+ * @private
+ */
+ _onTimeout: function () {
+ this._timeoutCallback();
+ },
+
+});
+
+return Timer;
+
+});
diff --git a/addons/mail/static/src/js/models/utils/timers.js b/addons/mail/static/src/js/models/utils/timers.js
new file mode 100644
index 00000000000..757945223f7
--- /dev/null
+++ b/addons/mail/static/src/js/models/utils/timers.js
@@ -0,0 +1,82 @@
+odoo.define('mail.model.Timers', function (require) {
+"use strict";
+
+var Timer = require('mail.model.Timer');
+
+var Class = require('web.Class');
+
+/**
+ * This class lists several timers that use a same callback and duration.
+ */
+var Timers = Class.extend({
+
+ /**
+ * Instantiate a new list of timers
+ *
+ * @param {Object} params
+ * @param {integer} params.duration duration of the underlying timers from
+ * start to timeout, in milli-seconds.
+ * @param {function} params.onTimeout a function to call back for underlying
+ * timers on timeout.
+ */
+ init: function (params) {
+ this._duration = params.duration;
+ this._timeoutCallback = params.onTimeout;
+ this._timers = {};
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * Register a timer with ID `timerID` to start.
+ *
+ * - an already registered timer with this ID is reset.
+ * - (optional) can provide a list of arguments that is passed to the
+ * function callback when timer times out.
+ *
+ * @param {Object} params
+ * @param {Array} [params.timeoutCallbackArguments]
+ * @param {integer} params.timerID
+ */
+ registerTimer: function (params) {
+ var timerID = params.timerID;
+ if (this._timers[timerID]) {
+ this._timers[timerID].clear();
+ }
+ var timerParams = {
+ duration: this._duration,
+ onTimeout: this._timeoutCallback,
+ };
+ if ('timeoutCallbackArguments' in params) {
+ timerParams.onTimeout = this._timeoutCallback.bind.apply(
+ this._timeoutCallback,
+ [null].concat(params.timeoutCallbackArguments)
+ );
+ } else {
+ timerParams.onTimeout = this._timeoutCallback;
+ }
+ this._timers[timerID] = new Timer(timerParams);
+ this._timers[timerID].start();
+ },
+ /**
+ * Unregister a timer with ID `timerID`. The unregistered timer is aborted
+ * and will not time out.
+ *
+ * @param {Object} params
+ * @param {integer} params.timerID
+ */
+ unregisterTimer: function (params) {
+ var timerID = params.timerID;
+ if (this._timers[timerID]) {
+ this._timers[timerID].clear();
+ delete this._timers[timerID];
+ }
+ },
+
+});
+
+return Timers;
+
+});