diff options
| author | Alexandre Kühn <aku@odoo.com> | 2018-08-24 00:33:10 +0200 |
|---|---|---|
| committer | Alexandre Kühn <aku@odoo.com> | 2018-08-27 18:32:58 +0200 |
| commit | eee49f13f00d7e934d399a023ad8d1b4b8ffa6b4 (patch) | |
| tree | 985588b07317f47c0faa129e3eaa81ef0001f0e1 /addons/mail/static/src | |
| parent | d5786447567b05e85edd43dbefe8e82f22dc2129 (diff) | |
[FIX][REF] mail: several thread windows fixes
This commit fixes some bugs on thread windows, and make some
improvements on tests related to thread windows.
Fixes:
1. Correctly position last visible thread window when there are more
open thread windows than available slots.
2. Closing a thread window now marks it as read.
3. Can now fold/unfold the blank thread window (aka 'New' thread window).
Tests cleaning:
1. Removed unnecessary 'before assertions' in thread window tests.
> Solved with this: https://github.com/odoo/odoo/commit/9b1daa1218f7adf9d741afba607ef5b55b16e3e6
1. Added basic rendering test for a (non-blank) thread window.
2. Cleaned thread window tests
> Split in different files.
> Grouped in 'Thread Window' QUnit module.
Diffstat (limited to 'addons/mail/static/src')
3 files changed, 77 insertions, 39 deletions
diff --git a/addons/mail/static/src/js/services/mail_window_manager.js b/addons/mail/static/src/js/services/mail_window_manager.js index 7b892fa8731..de614ba705f 100644 --- a/addons/mail/static/src/js/services/mail_window_manager.js +++ b/addons/mail/static/src/js/services/mail_window_manager.js @@ -11,8 +11,6 @@ var utils = require('web.utils'); var QWeb = core.qweb; var _t = core._t; -var THREAD_WINDOW_WIDTH = 325 + 5; // 5 pixels between windows - /** * Mail Window Manager * @@ -24,8 +22,12 @@ MailManager.include({ close_blank_thread_window: '_onCloseBlankThreadWindow', }), - // tell where to append thread window + // width of 'hidden thread window' dropdown button + HIDDEN_THREAD_WINDOW_DROPDOWN_BUTTON_WIDTH: 50, + // where thread windows are appended THREAD_WINDOW_APPENDTO: 'body', + // width of a thread window (+ 5 pixels between windows) + THREAD_WINDOW_WIDTH: 325 + 5, //-------------------------------------------------------------------------- // Public @@ -152,13 +154,28 @@ MailManager.include({ //-------------------------------------------------------------------------- /** - * Add the thread window such that it will be the left-most visible window + * Add the thread window such that it will be the left-most visible window. + * Note that adding a new thread window may decrement the amount of + * available slots for visible thread windows. + * For example: + * + * - global width of 800px + * - button width of 100px + * - thread width of 250px + * + * Without button: 3 thread windows (3*250px = 750px < 800px) + * With button: 2 thread windows (2*250px + 100px = 600px < 800px) + * + * So in order for the thread window to be the left-most visible window, + * we should compute available slots after insertion of the thread window. * * @private * @param {mail.ThreadWindow} threadWindow */ _addThreadWindow: function (threadWindow) { - this._computeAvailableSlotsForThreadWindows(this._threadWindows.length+1); + this._threadWindows.push(threadWindow); + this._computeAvailableSlotsForThreadWindows(); + this._threadWindows.pop(); this._threadWindows.splice(this._availableSlotsForThreadWindows-1, 0, threadWindow); }, /** @@ -206,22 +223,23 @@ MailManager.include({ * method call. * * @private - * @param {integer} nbWindows */ - _computeAvailableSlotsForThreadWindows: function (nbWindows) { + _computeAvailableSlotsForThreadWindows: function () { if (config.device.isMobile) { // one thread window full screen in mobile this._availableSlotsForThreadWindows = 1; return; } - var width = window.innerWidth; - var availableSlots = Math.floor(width/THREAD_WINDOW_WIDTH); - var spaceLeft = width - (Math.min(availableSlots, nbWindows)*THREAD_WINDOW_WIDTH); - if (availableSlots < nbWindows && spaceLeft < 50) { - // leave at least 50px for the hidden windows dropdown button + var GLOBAL_WIDTH = this._getGlobalWidth(); + var THREAD_WINDOW_NUM = this._threadWindows.length; + var availableSlots = Math.floor(GLOBAL_WIDTH/this.THREAD_WINDOW_WIDTH); + var spaceLeft = GLOBAL_WIDTH - (Math.min(availableSlots, THREAD_WINDOW_NUM)*this.THREAD_WINDOW_WIDTH); + if (availableSlots < THREAD_WINDOW_NUM && spaceLeft < this.HIDDEN_THREAD_WINDOW_DROPDOWN_BUTTON_WIDTH) { + // leave at least space for the hidden windows dropdown button availableSlots--; - spaceLeft += THREAD_WINDOW_WIDTH; + spaceLeft += this.THREAD_WINDOW_WIDTH; } + this._availableSlotsForThreadWindows = availableSlots; this._spaceLeftForThreadWindows = spaceLeft; }, @@ -242,6 +260,16 @@ MailManager.include({ }); }, /** + * Get the width of the browser, which is useful to determine how many + * open thread windows are visible or hidden. + * + * @private + * @returns {integer} + */ + _getGlobalWidth: function () { + return window.innerWidth; + }, + /** * Get thread window in the hidden windows matching ID `threadID`. * * Note: hidden windows are open windows that cannot be displayed @@ -320,7 +348,7 @@ MailManager.include({ if (this._hiddenThreadWindows.length) { this._$hiddenThreadWindowsDropdown = this._renderHiddenThreadWindowsDropdown(); var $hiddenWindowsDropdown = this._$hiddenThreadWindowsDropdown; - $hiddenWindowsDropdown.css({right: THREAD_WINDOW_WIDTH * this._availableSlotsForThreadWindows, bottom: 0 }) + $hiddenWindowsDropdown.css({right: this.THREAD_WINDOW_WIDTH * this._availableSlotsForThreadWindows, bottom: 0 }) .appendTo(this.THREAD_WINDOW_APPENDTO); this._repositionHiddenWindowsDropdown(); this._keepHiddenThreadWindowsDropdownOpen = false; @@ -469,15 +497,14 @@ MailManager.include({ * attribute `threadWindows` should be hidden. Those thread windows are put * in the hidden thread window dropdown menu. * + * This function assumes that we have already computed the available slots. + * * @private - * @param {integer} startIndex the index of the first thread window to hide, - * in increasing order of the thread windows in the `threadWindows` - * attribute */ - _repositionHiddenThreadWindows: function (startIndex) { + _repositionHiddenThreadWindows: function () { var hiddenWindows = []; var hiddenUnreadCounter = 0; - var index = startIndex; + var index = this._availableSlotsForThreadWindows; while (index < this._threadWindows.length) { var threadWindow = this._threadWindows[index]; hiddenWindows.push(threadWindow); @@ -508,27 +535,27 @@ MailManager.include({ if (this._areAllThreadWindowsHidden()) { return; } - this._computeAvailableSlotsForThreadWindows(this._threadWindows.length); - var availableSlots = this._availableSlotsForThreadWindows; + this._computeAvailableSlotsForThreadWindows(); - this._repositionVisibleThreadWindows(availableSlots-1); - this._repositionHiddenThreadWindows(availableSlots); + this._repositionVisibleThreadWindows(); + this._repositionHiddenThreadWindows(); }, /** * Reposition the thread windows that should be visible on the screen. * + * This function assumes that we have already computed the available slots. + * * @private - * @param {integer} count how many thread windows can should be visible, - * which are picked in the attribute `_threadWindows` in increasing index - * order of appearance in the array. constraint: - * 0 <= count < this._threadWindows.length */ - _repositionVisibleThreadWindows: function (count) { + _repositionVisibleThreadWindows: function () { var index = 0; - while (index < count && index < this._threadWindows.length) { + while ( + index < this._availableSlotsForThreadWindows && + index < this._threadWindows.length + ) { var threadWindow = this._threadWindows[index]; var cssProps = {bottom: 0}; - cssProps[_t.database.parameters.direction === 'rtl' ? 'left' : 'right'] = THREAD_WINDOW_WIDTH*index; + cssProps[_t.database.parameters.direction === 'rtl' ? 'left' : 'right'] = this.THREAD_WINDOW_WIDTH*index; threadWindow.$el.css(cssProps); threadWindow.do_show(); index++; diff --git a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js index 8d02db587a8..eb8a7da3634 100644 --- a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js +++ b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js @@ -10,9 +10,6 @@ var Widget = require('web.Widget'); var QWeb = core.qweb; var _t = core._t; -var HEIGHT_OPEN = '400px'; -var HEIGHT_FOLDED = '34px'; - /** * This is an abstract widget for rendering thread windows. * @@ -38,6 +35,9 @@ var AbstractThreadWindow = Widget.extend({ 'keydown .o_composer_text_field': '_onKeydown', 'keypress .o_composer_text_field': '_onKeypress', }, + FOLD_ANIMATION_DURATION: 200, // duration in ms for (un)fold transition + HEIGHT_OPEN: '400px', // height in px of thread window when open + HEIGHT_FOLDED: '34px', // height, in px, of thread window when folded /** * Children of this class must make use of `thread`, which is an object that * represent the thread that is linked to this thread window. @@ -85,7 +85,7 @@ var AbstractThreadWindow = Widget.extend({ }); if (this.isFolded()) { - this.$el.css('height', HEIGHT_FOLDED); + this.$el.css('height', this.HEIGHT_FOLDED); } else if (this.options.autofocus) { this._focusInput(); } @@ -301,8 +301,8 @@ var AbstractThreadWindow = Widget.extend({ */ _animateFold: function () { this.$el.animate({ - height: this.isFolded() ? HEIGHT_FOLDED : HEIGHT_OPEN - }, 200); + height: this.isFolded() ? this.HEIGHT_FOLDED : this.HEIGHT_OPEN + }, this.FOLD_ANIMATION_DURATION); }, /** * Set the focus on the composer of the thread window. This operation is @@ -368,6 +368,7 @@ var AbstractThreadWindow = Widget.extend({ }, /** * Update the fold state of the thread. + * * This function is called when toggling the fold state of this window. * If there is no thread linked to this window, it means this is the * "blank" thread window, therefore we use the internal state 'folded' @@ -380,6 +381,7 @@ var AbstractThreadWindow = Widget.extend({ this._thread.fold(folded); } else { this._folded = folded; + this.updateVisualFoldState(); } }, /** @@ -395,7 +397,8 @@ var AbstractThreadWindow = Widget.extend({ //-------------------------------------------------------------------------- /** - * Close the thread + * Close the thread window. + * Mark the thread as read if the thread window was open. * * @private * @param {MouseEvent} ev @@ -403,10 +406,18 @@ var AbstractThreadWindow = Widget.extend({ _onClickClose: function (ev) { ev.stopPropagation(); ev.preventDefault(); + if ( + this.hasThread() && + this._thread.getUnreadCounter() > 0 && + !this.isFolded() + ) { + this._thread.markAsRead(); + } this.close(); }, /** - * Fold/unfold the thread window + * Fold/unfold the thread window. + * Also mark the thread as read. * * @private */ diff --git a/addons/mail/static/src/xml/abstract_thread_window.xml b/addons/mail/static/src/xml/abstract_thread_window.xml index af72d5dd36c..de0418af3df 100644 --- a/addons/mail/static/src/xml/abstract_thread_window.xml +++ b/addons/mail/static/src/xml/abstract_thread_window.xml @@ -5,7 +5,7 @@ @param {mail.AbstractThreadWindow} widget --> <t t-name="mail.AbstractThreadWindow"> - <div class="o_thread_window o_in_home_menu"> + <div class="o_thread_window o_in_home_menu" t-att-data-thread-id="widget.getID()"> <div class="o_thread_window_header"> <t t-call="mail.AbstractThreadWindow.HeaderContent"> <t t-set="status" t-value="widget.getThreadStatus()"/> |
