diff options
| author | Alexandre Kühn <aku@odoo.com> | 2018-12-05 14:35:02 +0000 |
|---|---|---|
| committer | Alexandre Kühn <aku@odoo.com> | 2018-12-06 14:51:28 +0000 |
| commit | 7ad45a04e1a368f132fcc83bbe992ce0e98ed3d2 (patch) | |
| tree | 5b106206817e1f73251374879f6d18d174704559 /addons/mail/static/src | |
| parent | 9117d968e056d7c4e1112079e7e0ea0dd63cf9a5 (diff) | |
[IMP] im_livechat, mail: improved "is typing" notification
With this commit, the UI for "is typing..." notifications
has changed.
** before **:
In Discuss & chat windows, "is typing..." notification bar
at the bottom of the thread, inside the conversation.
** after **
In chat windows, animated '...' next to conversation name.
In Discuss, animated '...' next to conversation name in sidebar,
and text below the composer.
Task-ID 1881001
Diffstat (limited to 'addons/mail/static/src')
| -rw-r--r-- | addons/mail/static/src/js/composers/basic_composer.js | 21 | ||||
| -rw-r--r-- | addons/mail/static/src/js/discuss.js | 28 | ||||
| -rw-r--r-- | addons/mail/static/src/js/models/threads/thread_typing_mixin/thread_typing_mixin.js | 9 | ||||
| -rw-r--r-- | addons/mail/static/src/js/services/mail_window_manager.js | 20 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_widget.js | 28 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_windows/abstract_thread_window.js | 18 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_windows/thread_window.js | 17 | ||||
| -rw-r--r-- | addons/mail/static/src/scss/abstract_thread_window.scss | 12 | ||||
| -rw-r--r-- | addons/mail/static/src/scss/composer.scss | 5 | ||||
| -rw-r--r-- | addons/mail/static/src/scss/discuss.scss | 7 | ||||
| -rw-r--r-- | addons/mail/static/src/scss/thread.scss | 57 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/abstract_thread_window.xml | 3 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/composer.xml | 8 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/discuss.xml | 4 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/thread.xml | 28 |
15 files changed, 149 insertions, 116 deletions
diff --git a/addons/mail/static/src/js/composers/basic_composer.js b/addons/mail/static/src/js/composers/basic_composer.js index c8f7d702af4..1a40e3f48fa 100644 --- a/addons/mail/static/src/js/composers/basic_composer.js +++ b/addons/mail/static/src/js/composers/basic_composer.js @@ -123,6 +123,9 @@ var BasicComposer = Widget.extend({ $(window).on(this.fileuploadID, this._onAttachmentLoaded.bind(this)); this.on('change:attachment_ids', this, this._renderAttachments); + this.call('mail_service', 'getMailBus') + .on('update_typing_partners', this, this._onUpdateTypingPartners); + // Mention this._mentionManager.prependTo(this.$('.o_composer')); @@ -793,6 +796,24 @@ var BasicComposer = Widget.extend({ this._mentionManager.detectDelimiter(); } }, + /** + * @private + * @param {integer|string} threadID + */ + _onUpdateTypingPartners: function (threadID) { + if (!this.options.showTyping) { + return; + } + if (!this.options.thread) { + return; + } + if (this.options.thread.getID() !== threadID) { + return; + } + this.$('.o_composer_thread_typing').html(QWeb.render('mail.Composer.ThreadTyping', { + thread: this.options.thread, + })); + }, }); return BasicComposer; diff --git a/addons/mail/static/src/js/discuss.js b/addons/mail/static/src/js/discuss.js index 2cb9fe749d7..dd03f08028c 100644 --- a/addons/mail/static/src/js/discuss.js +++ b/addons/mail/static/src/js/discuss.js @@ -235,12 +235,14 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, { start: function () { var self = this; - this._basicComposer = new BasicComposer(this, - { mentionPartnersRestricted: true } - ); - this._extendedComposer = new ExtendedComposer(this, - { mentionPartnersRestricted: true } - ); + this._basicComposer = new BasicComposer(this, { + mentionPartnersRestricted: true, + showTyping: true, + }); + this._extendedComposer = new ExtendedComposer(this, { + mentionPartnersRestricted: true, + showTyping: true, + }); this._basicComposer .on('post_message', this, this._onPostMessage) .on('input_focused', this, this._onComposerFocused); @@ -1391,19 +1393,9 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, { }, /** * @private - * @param {integer|string} threadID */ - _onTypingPartnersUpdated: function (threadID) { - var self = this; - if (this._thread.getID() !== threadID) { - return; - } - if (this._thread.hasTypingNotification()) { - // call getMentionpartnerSuggestions in order to correctly fetch members - this._thread.getMentionPartnerSuggestions().then(function () { - self._threadWidget.renderTypingNotificationBar(self._thread); - }); - } + _onTypingPartnersUpdated: function () { + this._updateThreads(); }, /** * @private diff --git a/addons/mail/static/src/js/models/threads/thread_typing_mixin/thread_typing_mixin.js b/addons/mail/static/src/js/models/threads/thread_typing_mixin/thread_typing_mixin.js index fb1a3a91cd1..9a5b5abb4cc 100644 --- a/addons/mail/static/src/js/models/threads/thread_typing_mixin/thread_typing_mixin.js +++ b/addons/mail/static/src/js/models/threads/thread_typing_mixin/thread_typing_mixin.js @@ -148,6 +148,15 @@ var ThreadTypingMixin = { return true; }, /** + * Tells if someone other than current user is typing something on this + * thread. + * + * @returns {boolean} + */ + isSomeoneTyping: function () { + return !(_.isEmpty(this._typingPartnerIDs)); + }, + /** * Register someone that is currently typing something in this thread. * If this is the current user that is typing something, don't do anything * (we do not have to display anything) 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 79ea668e55e..64cf6bb88c9 100644 --- a/addons/mail/static/src/js/services/mail_window_manager.js +++ b/addons/mail/static/src/js/services/mail_window_manager.js @@ -329,8 +329,7 @@ MailManager.include({ .on('is_thread_bottom_visible', this, this._onIsThreadBottomVisible) .on('unsubscribe_from_channel', this, this._onUnsubscribeFromChannel) .on('update_thread_unread_counter', this, this._onUpdateThreadUnreadCounter) - .on('update_dm_presence', this, this._onUpdateDmPresence) - .on('update_typing_partners', this, this._onTypingPartnersUpdated); + .on('update_dm_presence', this, this._onUpdateDmPresence); core.bus.on('resize', this, _.debounce(this._repositionThreadWindows.bind(this), 100)); }, @@ -656,23 +655,6 @@ MailManager.include({ this._updateThreadWindowsFromMessage(message, { keepBottom: true, passively: true }); }, /** - * @private - * @param {integer|string} threadID - */ - _onTypingPartnersUpdated: function (threadID) { - var threadWindow = this._getThreadWindow(threadID); - if (!threadWindow) { - return; - } - var thread = this.getThread(threadID); - if (thread.isChannel()) { - // call getMentionpartnerSuggestions in order to correctly fetch members - thread.getMentionPartnerSuggestions().then(function () { - threadWindow.renderTypingNotificationBar(); - }); - } - }, - /** * Close the thread window when unsusbscribe from a channel. * * @private diff --git a/addons/mail/static/src/js/thread_widget.js b/addons/mail/static/src/js/thread_widget.js index e6da87c6dba..da74028903e 100644 --- a/addons/mail/static/src/js/thread_widget.js +++ b/addons/mail/static/src/js/thread_widget.js @@ -185,12 +185,6 @@ var ThreadWidget = Widget.extend({ dateFormat: time.getLangDatetimeFormat(), })); - // must be after mail.widget.Thread rendering, so that there is the - // DOM element for the 'is typing' notification bar - if (thread.hasTypingNotification()) { - this.renderTypingNotificationBar(thread); - } - _.each(messages, function (message) { var $message = self.$('.o_thread_message[data-message-id="'+ message.getID() +'"]'); $message.find('.o_mail_timestamp').data('date', message.getDate()); @@ -254,28 +248,6 @@ var ThreadWidget = Widget.extend({ return done; }, /** - * Render the 'is typing...' text on the typing notification bar of the - * thread. This is called when there is a change in the list of users - * typing something on this thread. - * - * @param {mail.model.AbstractThread} thread with ThreadTypingMixin - */ - renderTypingNotificationBar: function (thread) { - if (this._currentThreadID === thread.getID()) { - var shouldScrollToBottomAfterRendering = this.isAtBottom(); - - // typing notification bar rendering - var $typingBar = this.$('.o_thread_typing_notification_bar'); - var text = thread.getTypingMembersToText(); - $typingBar.toggleClass('o_hidden', !text); // hide if no text, because of padding - $typingBar.text(text); - - if (shouldScrollToBottomAfterRendering) { - this.scrollToBottom(); - } - } - }, - /** * Scroll to the bottom of the thread */ scrollToBottom: function () { 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 f4bf9533ff9..3e4e2e16325 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 @@ -139,6 +139,15 @@ var AbstractThreadWindow = Widget.extend({ return this._getThreadID(); }, /** + * @returns {mail.model.Thread|undefined} + */ + getThread: function () { + if (!this.hasThread) { + return undefined; + } + return this._thread; + }, + /** * Get the status of the thread, such as the im status of a DM chat * ('online', 'offline', etc.). If this window has no thread, returns * `undefined`. @@ -257,14 +266,6 @@ var AbstractThreadWindow = Widget.extend({ QWeb.render('mail.AbstractThreadWindow.HeaderContent', options)); }, /** - * Render the 'is typing...' notification bar text on the thread in this - * thread window. This is called when there is a change in the list of users - * currently typing something on this thread. - */ - renderTypingNotificationBar: function () { - this._threadWidget.renderTypingNotificationBar(this._thread); - }, - /** * Scroll to the bottom of the thread in the thread window */ scrollToBottom: function () { @@ -339,6 +340,7 @@ var AbstractThreadWindow = Widget.extend({ _getHeaderRenderingOptions: function () { return { status: this.getThreadStatus(), + thread: this.getThread(), title: this.getTitle(), unreadCounter: this.getUnreadCounter(), widget: this, diff --git a/addons/mail/static/src/js/thread_windows/thread_window.js b/addons/mail/static/src/js/thread_windows/thread_window.js index 62468e9ea16..f4b0137c476 100644 --- a/addons/mail/static/src/js/thread_windows/thread_window.js +++ b/addons/mail/static/src/js/thread_windows/thread_window.js @@ -55,6 +55,9 @@ var ThreadWindow = AbstractThreadWindow.extend({ var superDef = this._super().then(this._listenThreadWidget.bind(this)); + this.call('mail_service', 'getMailBus') + .on('update_typing_partners', this, this._onUpdateTypingPartners); + var composerDef; if (!this.hasThread()) { this._startWithoutThread(); @@ -353,7 +356,19 @@ var ThreadWindow = AbstractThreadWindow.extend({ var message = this.call('mail_service', 'getMessage', messageID); message.toggleStarStatus(); }, - + /** + * @private + * @param {integer|string} threadID + */ + _onUpdateTypingPartners: function (threadID) { + if (!this.hasThread()) { + return; + } + if (this._thread.getID() !== threadID) { + return; + } + this.renderHeader(); + }, }); return ThreadWindow; diff --git a/addons/mail/static/src/scss/abstract_thread_window.scss b/addons/mail/static/src/scss/abstract_thread_window.scss index a4ad6d366cc..b148afa111f 100644 --- a/addons/mail/static/src/scss/abstract_thread_window.scss +++ b/addons/mail/static/src/scss/abstract_thread_window.scss @@ -57,6 +57,14 @@ $o-mail-thread-window-zindex: $zindex-modal + 1 !default; cursor: pointer; flex: 1 1 auto; @include o-text-overflow; + + .o_mail_thread_typing_icon { + padding-left: 2px; + + .o_mail_thread_typing_icon_dot { + background: gray('300'); + } + } } .o_thread_window_buttons { @@ -76,10 +84,6 @@ $o-mail-thread-window-zindex: $zindex-modal + 1 !default; overflow: auto; -webkit-overflow-scrolling: touch; // smooth scrolling in iOS app (Safari) - .o_thread_typing_notification_bar { - background-color: rgba($o-mail-thread-window-bg, 0.75); - } - .o_thread_date_separator { margin: 0px 0px 15px 0px; .o_thread_date { diff --git a/addons/mail/static/src/scss/composer.scss b/addons/mail/static/src/scss/composer.scss index e076629f667..f12e195abe9 100644 --- a/addons/mail/static/src/scss/composer.scss +++ b/addons/mail/static/src/scss/composer.scss @@ -184,6 +184,11 @@ flex: 1 0 100%; } + .o_composer_thread_typing { + font-size: 0.9em; + color: gray('600'); + } + .o_chatter_composer_tools { border: none; border-left: 1px solid gray('300'); diff --git a/addons/mail/static/src/scss/discuss.scss b/addons/mail/static/src/scss/discuss.scss index 8d328b028bf..39c30aefa05 100644 --- a/addons/mail/static/src/scss/discuss.scss +++ b/addons/mail/static/src/scss/discuss.scss @@ -44,6 +44,9 @@ flex: 1 1 auto; @include o-text-overflow; } + .o_mail_thread_typing_icon_dot { + background: gray('600');; + } .o_mail_sidebar_needaction, .o_mail_partner_unpin, .o_mail_channel_settings { flex: 0 0 auto; } @@ -129,7 +132,7 @@ background-color: darken(gray('900'),2%); .o_mail_partner_unpin, .o_mail_channel_settings { - opacity: $o-mail-sidebar-icon-opacity; + display: inline-block; } } @@ -143,7 +146,7 @@ } .o_mail_partner_unpin, .o_mail_channel_settings { - @include o-hover-opacity($default-opacity: 0, $hover-opacity: 1); + display: none; } &.o_unread_message { color: white; diff --git a/addons/mail/static/src/scss/thread.scss b/addons/mail/static/src/scss/thread.scss index 81f6862ca9f..a56f54bad78 100644 --- a/addons/mail/static/src/scss/thread.scss +++ b/addons/mail/static/src/scss/thread.scss @@ -13,26 +13,6 @@ height: 15px; } - .o_thread_typing_notification_free_space { - flex-grow: 1, - } - - .o_thread_typing_notification_bar { - flex: 0, 0, 20px; - background-color: rgba($white, 0.75); - padding: 5px; - text-align: center; - color: gray('600'); - - &.o_thread_order_asc { - @include o-position-sticky($bottom: 0px); - } - - &.o_thread_order_desc { - @include o-position-sticky($top: 0px); - } - } - .o_thread_tooltip_container { display: inline; position: relative; @@ -239,3 +219,40 @@ opacity: $o-mail-thread-icon-opacity; } } + +// ------------------------------------------------------------------ +// Thread typing icon: shared between discuss and chat windows +// ------------------------------------------------------------------ + +.o_mail_thread_typing_icon { + position: relative; + text-align: center; + margin-left: auto; + margin-right: auto; + + .o_mail_thread_typing_icon_dot { + display: inline-block; + width: 3px; + height: 3px; + border-radius: 50%; + background: gray('800'); + animation: o_mail_thread_typing_icon_dot 1.5s linear infinite; + + &:nth-child(2) { + animation-delay: -1.35s; + } + + &:nth-child(3) { + animation-delay: -1.2s; + } + } +} + +@keyframes o_mail_thread_typing_icon_dot { + 0%, 40%, 100% { + transform: initial; + } + 20% { + transform: translateY(-5px); + } +} diff --git a/addons/mail/static/src/xml/abstract_thread_window.xml b/addons/mail/static/src/xml/abstract_thread_window.xml index de0418af3df..89c45323c7a 100644 --- a/addons/mail/static/src/xml/abstract_thread_window.xml +++ b/addons/mail/static/src/xml/abstract_thread_window.xml @@ -11,6 +11,7 @@ <t t-set="status" t-value="widget.getThreadStatus()"/> <t t-set="title" t-value="widget.getTitle()"/> <t t-set="unreadCounter" t-value="widget.getUnreadCounter()"/> + <t t-set="thread" t-value="widget.getThread()"/> </t> </div> <div class="o_thread_window_content"> @@ -58,6 +59,7 @@ name of the document. @param {integer} [unreadCounter] the number of unread messages on the thread. + @param {mail.model.Thread|undefined} thread @param {Object} widget @param {function} widget.isMobile function without any param that states whether it should render for desktop or mobile screen. @@ -70,6 +72,7 @@ <t t-if="status" t-call="mail.UserStatus"/> <t t-esc="title"/> <span t-if="unreadCounter"> (<t t-esc="unreadCounter"/>)</span> + <t t-if="thread and thread.hasTypingNotification() and thread.isSomeoneTyping()" t-call="mail.ThreadTypingIcon"/> </span> <span t-if="!widget.isMobile()" class="o_thread_window_buttons"> <a href="#" class="o_thread_window_close fa fa-close"/> diff --git a/addons/mail/static/src/xml/composer.xml b/addons/mail/static/src/xml/composer.xml index 883c9752035..6147197cd17 100644 --- a/addons/mail/static/src/xml/composer.xml +++ b/addons/mail/static/src/xml/composer.xml @@ -24,6 +24,7 @@ </div> </div> <div class="o_composer_attachments_list"/> + <div class="o_composer_thread_typing"/> </div> <div class="o_composer_send"> <button tabindex="3" class="btn btn-primary o_composer_button_send d-none d-md-inline-block" type="button"><t t-esc="widget.options.sendText"/></button> @@ -40,6 +41,13 @@ </span> </div> + <!-- + @param {mail.model.Thread} thread + --> + <t t-name="mail.Composer.ThreadTyping"> + <t t-esc="thread.getTypingMembersToText()"/> + </t> + <div t-name="mail.Composer.emojis" class="o_mail_emoji_container"> <t t-foreach="emojis" t-as="emoji"> <button t-att-data-emoji="emoji.sources[0]" class="btn btn-link o_mail_emoji" t-att-title="emoji.description" t-att-aria-label="emoji.description"> diff --git a/addons/mail/static/src/xml/discuss.xml b/addons/mail/static/src/xml/discuss.xml index 605dcb53956..f97e38768e4 100644 --- a/addons/mail/static/src/xml/discuss.xml +++ b/addons/mail/static/src/xml/discuss.xml @@ -140,6 +140,10 @@ <t t-esc="_.unescape(thread.getName())"/> <i t-if="thread.isMassMailing()" class="fa fa-envelope-o" title="Sends messages by email" role="img" aria-label="Send by mail"/> </span> + <t t-if="channel.hasTypingNotification() and channel.isSomeoneTyping()"> + <t t-set="thread" t-value="channel"/> + <t t-call="mail.ThreadTypingIcon"/> + </t> <span t-attf-class="fa fa-cog o_mail_channel_settings" title="Channel settings" role="img" aria-label="Channel settings" t-att-data-thread-id="thread.getID()"/> <t t-call="mail.discuss.SidebarCounter"/> diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml index f28e071b2f3..a1e2d52e2ad 100644 --- a/addons/mail/static/src/xml/thread.xml +++ b/addons/mail/static/src/xml/thread.xml @@ -191,7 +191,6 @@ <t t-if="options.displayBottomThreadFreeSpace"> <div class="o_thread_bottom_free_space"/> </t> - <t t-if="thread.hasTypingNotification()" t-call="mail.widget.Thread.TypingNotificationBar"/> </div> </t> @@ -217,27 +216,12 @@ <div class="o_mail_thread_content"> <t t-if="options.messagesSeparatorPosition == 'top'" t-call="mail.MessagesSeparator"/> <t t-set="messages" t-value="messages.slice().reverse()"/> - <t t-if="thread.hasTypingNotification()" t-call="mail.widget.Thread.TypingNotificationBar"/> <t t-call="mail.widget.Thread.Messages"/> <t t-if="options.displayLoadMore" t-call="mail.widget.Thread.LoadMore"/> </div> </t> <!-- - @param {mail.model.AbstractThread} thread - --> - <t t-name="mail.widget.Thread.TypingNotificationBar"> - <t t-if="options.displayOrder === ORDER.ASC"> - <div class="o_thread_typing_notification_free_space"/> - <div class="o_thread_typing_notification_bar o_thread_order_asc"/> - </t> - <t t-else=""> - <div class="o_thread_typing_notification_free_space"/> - <div class="o_thread_typing_notification_bar o_thread_order_desc"/> - </t> - </t> - - <!-- @param {mail.model.AbstractMessage[]} messages messages are ordered based on desired display order --> @@ -550,4 +534,16 @@ </t> </div> </t> + + <!-- + @param {mail.model.Thread} thread with typing feature + --> + <t t-name="mail.ThreadTypingIcon"> + <span class="o_mail_thread_typing_icon" t-att-title="thread.getTypingMembersToText()"> + <span class="o_mail_thread_typing_icon_dot"/> + <span class="o_mail_thread_typing_icon_dot"/> + <span class="o_mail_thread_typing_icon_dot"/> + </span> + </t> + </templates> |
