diff --git a/addons/im_livechat/static/src/components/discuss/discuss.js b/addons/im_livechat/static/src/components/discuss/discuss.js deleted file mode 100644 index 2a18e8c1621..00000000000 --- a/addons/im_livechat/static/src/components/discuss/discuss.js +++ /dev/null @@ -1,26 +0,0 @@ -/** @odoo-module **/ - -import { Discuss } from '@mail/components/discuss/discuss'; - -import { patch } from 'web.utils'; - -const components = { Discuss }; - -patch(components.Discuss.prototype, 'im_livechat/static/src/components/discuss/discuss.js', { - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - /** - * @override - */ - mobileNavbarTabs(...args) { - return [...this._super(...args), { - icon: 'fa fa-comments', - id: 'livechat', - label: this.env._t("Livechat"), - }]; - } - -}); diff --git a/addons/im_livechat/static/src/models/messaging/messaging.js b/addons/im_livechat/static/src/models/messaging/messaging.js new file mode 100644 index 00000000000..49e116c21f5 --- /dev/null +++ b/addons/im_livechat/static/src/models/messaging/messaging.js @@ -0,0 +1,16 @@ +/** @odoo-module **/ + +import { addFields } from '@mail/model/model_core'; +import { one2many } from '@mail/model/model_field'; +// ensure that the model definition is loaded before the patch +import '@mail/models/messaging/messaging'; + +addFields('Messaging', { + /** + * All pinned livechats that are known. + */ + pinnedLivechats: one2many('Thread', { + inverse: 'messagingAsPinnedLivechat', + readonly: true, + }), +}); diff --git a/addons/im_livechat/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js b/addons/im_livechat/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js new file mode 100644 index 00000000000..be26bf92e80 --- /dev/null +++ b/addons/im_livechat/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js @@ -0,0 +1,22 @@ +/** @odoo-module **/ + +import { patchRecordMethods } from '@mail/model/model_core'; +// ensure that the model definition is loaded before the patch +import '@mail/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view'; + +patchRecordMethods('MobileMessagingNavbarView', { + /** + * @override + */ + _computeTabs() { + const res = this._super(); + if (this.messaging.pinnedLivechats.length > 0) { + return [...res, { + icon: 'fa fa-comments', + id: 'livechat', + label: this.env._t("Livechat"), + }]; + } + return res; + }, +}); diff --git a/addons/im_livechat/static/src/models/thread/thread.js b/addons/im_livechat/static/src/models/thread/thread.js index 1bc92847a5e..8c20a97a34c 100644 --- a/addons/im_livechat/static/src/models/thread/thread.js +++ b/addons/im_livechat/static/src/models/thread/thread.js @@ -1,10 +1,34 @@ /** @odoo-module **/ -import { patchModelMethods, patchRecordMethods } from '@mail/model/model_core'; -import { insert, link, unlink } from '@mail/model/model_field_command'; +import { addFields, addRecordMethods, patchModelMethods, patchRecordMethods } from '@mail/model/model_core'; +import { many2one } from '@mail/model/model_field'; +import { clear, insert, link, replace, unlink } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/thread/thread'; +addFields('Thread', { + /** + * If set, current thread is a livechat. + */ + messagingAsPinnedLivechat: many2one('Messaging', { + compute: '_computeMessagingAsPinnedLivechat', + inverse: 'pinnedLivechats', + }), +}); + +addRecordMethods('Thread', { + /** + * @private + * @returns {FieldCommand} + */ + _computeMessagingAsPinnedLivechat() { + if (!this.messaging || this.channel_type !== 'livechat' || !this.isPinned) { + return clear(); + } + return replace(this.messaging); + }, +}); + patchModelMethods('Thread', { /** * @override diff --git a/addons/mail/static/src/components/discuss/discuss.js b/addons/mail/static/src/components/discuss/discuss.js index e83ddb1a4c0..352fdc0fb10 100644 --- a/addons/mail/static/src/components/discuss/discuss.js +++ b/addons/mail/static/src/components/discuss/discuss.js @@ -21,7 +21,6 @@ export class Discuss extends Component { useUpdate({ func: () => this._update() }); onWillUnmount(() => this._willUnmount()); this._onHideMobileAddItemHeader = this._onHideMobileAddItemHeader.bind(this); - this._onSelectMobileNavbarTab = this._onSelectMobileNavbarTab.bind(this); } _update() { @@ -78,25 +77,6 @@ export class Discuss extends Component { return this.messaging && this.messaging.discuss; } - /** - * @returns {Object[]} - */ - mobileNavbarTabs() { - return [{ - icon: 'fa fa-inbox', - id: 'mailbox', - label: this.env._t("Mailboxes"), - }, { - icon: 'fa fa-user', - id: 'chat', - label: this.env._t("Chat"), - }, { - icon: 'fa fa-users', - id: 'channel', - label: this.env._t("Channel"), - }]; - } - //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -169,33 +149,6 @@ export class Discuss extends Component { } } - /** - * @private - * @param {Object} detail - * @param {string} detail.tabId - */ - _onSelectMobileNavbarTab(detail) { - if (this.discuss.activeMobileNavbarTabId === detail.tabId) { - return; - } - this.discuss.update({ activeMobileNavbarTabId: detail.tabId }); - if ( - this.discuss.activeMobileNavbarTabId === 'mailbox' && - (!this.discuss.thread || this.discuss.thread.model !== 'mailbox') - ) { - this.discuss.update({ thread: link(this.messaging.inbox) }); - } - if (this.discuss.activeMobileNavbarTabId !== 'mailbox') { - this.discuss.update({ thread: unlink() }); - } - if (this.discuss.activeMobileNavbarTabId !== 'chat') { - this.discuss.update({ isAddingChat: false }); - } - if (this.discuss.activeMobileNavbarTabId !== 'channel') { - this.discuss.update({ isAddingChannel: false }); - } - } - } Object.assign(Discuss, { diff --git a/addons/mail/static/src/components/discuss/discuss.xml b/addons/mail/static/src/components/discuss/discuss.xml index c95ef4995e1..6a9a03bc3c1 100644 --- a/addons/mail/static/src/components/discuss/discuss.xml +++ b/addons/mail/static/src/components/discuss/discuss.xml @@ -76,12 +76,10 @@ filter="discuss.activeMobileNavbarTabId" /> - + diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu.js b/addons/mail/static/src/components/messaging_menu/messaging_menu.js index 41bf9e654ed..6a6269c258e 100644 --- a/addons/mail/static/src/components/messaging_menu/messaging_menu.js +++ b/addons/mail/static/src/components/messaging_menu/messaging_menu.js @@ -23,7 +23,6 @@ export class MessagingMenu extends Component { this._onMobileNewMessageInputSource = this._onMobileNewMessageInputSource.bind(this); this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this); this._onHideMobileNewMessage = this._onHideMobileNewMessage.bind(this); - this._onSelectMobileNavbarTab = this._onSelectMobileNavbarTab.bind(this); onMounted(() => this._mounted()); onWillUnmount(() => this._willUnmount()); } @@ -54,25 +53,6 @@ export class MessagingMenu extends Component { return this.env._t("Search user..."); } - /** - * @returns {Object[]} - */ - get tabs() { - return [{ - icon: 'fa fa-envelope', - id: 'all', - label: this.env._t("All"), - }, { - icon: 'fa fa-user', - id: 'chat', - label: this.env._t("Chat"), - }, { - icon: 'fa fa-users', - id: 'channel', - label: this.env._t("Channel"), - }]; - } - //-------------------------------------------------------------------------- // Handlers //-------------------------------------------------------------------------- @@ -171,15 +151,6 @@ export class MessagingMenu extends Component { }); } - /** - * @private - * @param {Object} detail - * @param {string} detail.tabId - */ - _onSelectMobileNavbarTab(detail) { - this.messagingMenu.update({ activeTabId: detail.tabId }); - } - } Object.assign(MessagingMenu, { diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu.xml b/addons/mail/static/src/components/messaging_menu/messaging_menu.xml index 8ea24d7613c..91ed07d5313 100644 --- a/addons/mail/static/src/components/messaging_menu/messaging_menu.xml +++ b/addons/mail/static/src/components/messaging_menu/messaging_menu.xml @@ -54,12 +54,10 @@ classNameObj="{ 'o-mobile': messaging.device.isMobile }" filter="messagingMenu.activeTabId" /> - + diff --git a/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.js b/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.js index 98b7dceca18..fd9e5e4854d 100644 --- a/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.js +++ b/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.js @@ -6,50 +6,20 @@ const { Component } = owl; export class MobileMessagingNavbar extends Component { - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - /** - * @private - * @param {MouseEvent} ev + * @returns {MobileMessagingNavbarView} */ - _onClick(ev) { - if (this.props.onSelectMobileMessagingNavbarTab) { - this.props.onSelectMobileMessagingNavbarTab({ - tabId: ev.currentTarget.dataset.tabId, - }); - } + get mobileMessagingNavbarView() { + return this.messaging && this.messaging.models['MobileMessagingNavbarView'].get(this.props.mobileMessagingNavbarViewLocalId); } } Object.assign(MobileMessagingNavbar, { - defaultProps: { - tabs: [], - }, props: { - activeTabId: String, - onSelectMobileMessagingNavbarTab: { - type: Function, - optional: true, - }, - tabs: { - type: Array, - element: { - type: Object, - shape: { - icon: { - type: String, - optional: true, - }, - id: String, - label: String, - }, - }, - }, + mobileMessagingNavbarViewLocalId: String, }, template: 'mail.MobileMessagingNavbar', }); -registerMessagingComponent(MobileMessagingNavbar, { propsCompareDepth: { tabs: 2 } }); +registerMessagingComponent(MobileMessagingNavbar); diff --git a/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.xml b/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.xml index 8dd1bd4b31e..7b5d16cade5 100644 --- a/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.xml +++ b/addons/mail/static/src/components/mobile_messaging_navbar/mobile_messaging_navbar.xml @@ -3,13 +3,15 @@
- -
- - - - -
+ + +
+ + + + +
+
diff --git a/addons/mail/static/src/models/discuss/discuss.js b/addons/mail/static/src/models/discuss/discuss.js index 338be2dfde2..c186f3b0ea1 100644 --- a/addons/mail/static/src/models/discuss/discuss.js +++ b/addons/mail/static/src/models/discuss/discuss.js @@ -285,6 +285,20 @@ registerModel({ } return this.isAddingChat; }, + /** + * @private + * @returns {FieldCommand} + */ + _computeMobileMessagingNavbarView() { + if ( + this.messaging.device && + this.messaging.device.isMobile && + !(this.threadView && this.threadView.replyingToMessageView) + ) { + return insertAndReplace(); + } + return clear(); + }, /** * Only pinned threads are allowed in discuss. * @@ -387,6 +401,15 @@ registerModel({ menu_id: attr({ default: null, }), + /** + * The navbar view on the discuss app when in mobile and when not + * replying to a message from inbox. + */ + mobileMessagingNavbarView: one2one('MobileMessagingNavbarView', { + compute: '_computeMobileMessagingNavbarView', + inverse: 'discuss', + isCausal: true, + }), /** * Quick search input value in the discuss sidebar (desktop). Useful * to filter channels and chats based on this input content. diff --git a/addons/mail/static/src/models/messaging_menu/messaging_menu.js b/addons/mail/static/src/models/messaging_menu/messaging_menu.js index a0e7b77aa65..73dfa549ad2 100644 --- a/addons/mail/static/src/models/messaging_menu/messaging_menu.js +++ b/addons/mail/static/src/models/messaging_menu/messaging_menu.js @@ -1,7 +1,8 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { attr, one2many } from '@mail/model/model_field'; +import { attr, one2many, one2one } from '@mail/model/model_field'; +import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'MessagingMenu', @@ -48,6 +49,16 @@ registerModel({ const notificationPemissionCounter = this.messaging.isNotificationPermissionDefault ? 1 : 0; return inboxCounter + unreadChannelsCounter + notificationGroupsCounter + notificationPemissionCounter; }, + /** + * @private + * @returns {MobileMessagingNavbarView|FieldCommand} + */ + _computeMobileMessagingNavbarView() { + if (this.messaging.device && this.messaging.device.isMobile) { + return insertAndReplace(); + } + return clear(); + }, }, fields: { /** @@ -77,10 +88,18 @@ registerModel({ isOpen: attr({ default: false, }), + /** + * The navbar view on the messaging menu when in mobile. + */ + mobileMessagingNavbarView: one2one('MobileMessagingNavbarView', { + compute: '_computeMobileMessagingNavbarView', + inverse: 'messagingMenu', + isCausal: true, + }), /** * States all the pinned channels that have unread messages. */ - pinnedAndUnreadChannels: one2many('Thread', { + pinnedAndUnreadChannels: one2many('Thread', { inverse: 'messagingMenuAsPinnedAndUnreadChannel', readonly: true, }), diff --git a/addons/mail/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js b/addons/mail/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js new file mode 100644 index 00000000000..4146aed094a --- /dev/null +++ b/addons/mail/static/src/models/mobile_messaging_navbar_view/mobile_messaging_navbar_view.js @@ -0,0 +1,120 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, one2one } from '@mail/model/model_field'; +import { clear, replace } from '@mail/model/model_field_command'; + +registerModel({ + name: 'MobileMessagingNavbarView', + identifyingFields: [['discuss', 'messagingMenu']], + recordMethods: { + /** + * @param {string} tabId + */ + onClick(tabId) { + if (this.discuss) { + if (this.discuss.activeMobileNavbarTabId === tabId) { + return; + } + this.discuss.update({ activeMobileNavbarTabId: tabId }); + if ( + this.discuss.activeMobileNavbarTabId === 'mailbox' && + (!this.discuss.thread || this.discuss.thread.model !== 'mailbox') + ) { + this.discuss.update({ thread: replace(this.messaging.inbox) }); + } + if (this.discuss.activeMobileNavbarTabId !== 'mailbox') { + this.discuss.update({ thread: clear() }); + } + if (this.discuss.activeMobileNavbarTabId !== 'chat') { + this.discuss.update({ isAddingChat: false }); + } + if (this.discuss.activeMobileNavbarTabId !== 'channel') { + this.discuss.update({ isAddingChannel: false }); + } + } + if (this.messagingMenu) { + this.messagingMenu.update({ activeTabId: tabId }); + } + }, + /** + * @private + * @returns {string|FieldCommand} + */ + _computeActiveTabId() { + if (this.discuss) { + return this.discuss.activeMobileNavbarTabId; + } + if (this.messagingMenu) { + return this.messagingMenu.activeTabId; + } + return clear(); + }, + /** + * @private + * @returns {Object[]} + */ + _computeTabs() { + if (this.discuss) { + return [{ + icon: 'fa fa-inbox', + id: 'mailbox', + label: this.env._t("Mailboxes"), + }, { + icon: 'fa fa-user', + id: 'chat', + label: this.env._t("Chat"), + }, { + icon: 'fa fa-users', + id: 'channel', + label: this.env._t("Channel"), + }]; + } + if (this.messagingMenu) { + return [{ + icon: 'fa fa-envelope', + id: 'all', + label: this.env._t("All"), + }, { + icon: 'fa fa-user', + id: 'chat', + label: this.env._t("Chat"), + }, { + icon: 'fa fa-users', + id: 'channel', + label: this.env._t("Channel"), + }]; + } + return []; + }, + }, + fields: { + /** + * Tab selected in this navbar. + * Either 'all', 'mailbox', 'chat' or 'channel'. + */ + activeTabId: attr({ + compute: '_computeActiveTabId', + }), + discuss: one2one('Discuss', { + inverse: 'mobileMessagingNavbarView', + readonly: true, + }), + messagingMenu: one2one('MessagingMenu', { + inverse: 'mobileMessagingNavbarView', + readonly: true, + }), + /** + * Ordered list of tabs that this navbar has. + * Format of tab: + * { + * icon: + * id: + * label: + * } + */ + tabs: attr({ + compute: '_computeTabs', + }), + }, +});