diff options
| author | Alexandre Kühn <aku@odoo.com> | 2018-12-05 14:35:26 +0000 |
|---|---|---|
| committer | Alexandre Kühn <aku@odoo.com> | 2018-12-06 16:18:09 +0000 |
| commit | 15bbadb69b1b26404a614736c3cde7980d3c1dfd (patch) | |
| tree | 81dd1957900c612d5a06830f172b685b1326f11e /addons/mail/static/src/js/models/utils | |
| parent | 50dfa865ea32c88d55e7eb0fce6a6ae978c9c3b4 (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.js | 181 | ||||
| -rw-r--r-- | addons/mail/static/src/js/models/utils/timer.js | 69 | ||||
| -rw-r--r-- | addons/mail/static/src/js/models/utils/timers.js | 82 |
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; + +}); |
