From 2e2b49931f5c80e17e82cdc2dbabdf9ae98833b9 Mon Sep 17 00:00:00 2001 From: "Didier (did)" Date: Tue, 12 Oct 2021 14:43:50 +0000 Subject: [PATCH] [FIX] mail: add the ability to invite on mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, it was impossible for a user to invite people to a channel or a group DM. This commit add the invite button on the chat windows header only on mobile. Part of task-2634175 closes odoo/odoo#78267 X-original-commit: 56ab9ffea28dd5f22a74ba269cbd5552c42953e3 Signed-off-by: Alexandre Kühn (aku) --- .../channel_invitation_form.scss | 5 -- .../components/chat_window/chat_window.scss | 5 ++ .../components/chat_window/chat_window.xml | 5 +- .../chat_window_header/chat_window_header.js | 1 + .../chat_window_header/chat_window_header.xml | 12 ++++ .../components/popover_view/popover_view.scss | 5 ++ .../components/popover_view/popover_view.xml | 2 +- .../channel_invitation_form.js | 35 ++++++++-- .../src/models/chat_window/chat_window.js | 64 ++++++++++++++++++- 9 files changed, 118 insertions(+), 16 deletions(-) diff --git a/addons/mail/static/src/components/channel_invitation_form/channel_invitation_form.scss b/addons/mail/static/src/components/channel_invitation_form/channel_invitation_form.scss index 3d872d30d18..1d3fecfd1f3 100644 --- a/addons/mail/static/src/components/channel_invitation_form/channel_invitation_form.scss +++ b/addons/mail/static/src/components/channel_invitation_form/channel_invitation_form.scss @@ -2,11 +2,6 @@ // Layout // ------------------------------------------------------------------ -.o_ChannelInvitationForm { - width: Min(95vw, 400px); - max-height: Min(calc(100vh - 140px), 530px); -} - .o_ChannelInvitationForm_selectablePartnerAvatarContainer { width: 32px; height: 32px; diff --git a/addons/mail/static/src/components/chat_window/chat_window.scss b/addons/mail/static/src/components/chat_window/chat_window.scss index 7261bc29cb9..e9a5a66e658 100644 --- a/addons/mail/static/src/components/chat_window/chat_window.scss +++ b/addons/mail/static/src/components/chat_window/chat_window.scss @@ -7,6 +7,7 @@ bottom: 0; display: flex; flex-flow: column; + overflow: auto; &:not(.o-mobile) { max-width: 100%; @@ -32,6 +33,10 @@ } } +.o_ChatWindow_channelInvitationForm { + min-height: 450px; // allow flex shrink smaller than content (but not too small) +} + .o_ChatWindow_header { flex: 0 0 auto; } diff --git a/addons/mail/static/src/components/chat_window/chat_window.xml b/addons/mail/static/src/components/chat_window/chat_window.xml index 4400df8dc14..8bbbb61e837 100644 --- a/addons/mail/static/src/components/chat_window/chat_window.xml +++ b/addons/mail/static/src/components/chat_window/chat_window.xml @@ -23,7 +23,10 @@ - + + + + + + +
+ +
+
+ +
+ +
+
+
diff --git a/addons/mail/static/src/components/popover_view/popover_view.scss b/addons/mail/static/src/components/popover_view/popover_view.scss index e0f99263752..4b6599ce46f 100644 --- a/addons/mail/static/src/components/popover_view/popover_view.scss +++ b/addons/mail/static/src/components/popover_view/popover_view.scss @@ -7,6 +7,11 @@ border: $border-width solid; } +.o_PopoverView_channelInvitationForm { + width: Min(95vw, 400px); + max-height: Min(calc(100vh - 140px), 530px); +} + // ------------------------------------------------------------------ // Style // ------------------------------------------------------------------ diff --git a/addons/mail/static/src/components/popover_view/popover_view.xml b/addons/mail/static/src/components/popover_view/popover_view.xml index 1f6b81b57db..7be1648da80 100644 --- a/addons/mail/static/src/components/popover_view/popover_view.xml +++ b/addons/mail/static/src/components/popover_view/popover_view.xml @@ -4,7 +4,7 @@
- +
diff --git a/addons/mail/static/src/models/channel_invitation_form/channel_invitation_form.js b/addons/mail/static/src/models/channel_invitation_form/channel_invitation_form.js index 274913df0cb..37d12545ae3 100644 --- a/addons/mail/static/src/models/channel_invitation_form/channel_invitation_form.js +++ b/addons/mail/static/src/models/channel_invitation_form/channel_invitation_form.js @@ -2,7 +2,7 @@ import { registerNewModel } from '@mail/model/model_core'; import { attr, many2many, many2one, one2one } from '@mail/model/model_field'; -import { clear, insertAndReplace, link, unlink, unlinkAll } from '@mail/model/model_field_command'; +import { clear, insertAndReplace, link, replace, unlink, unlinkAll } from '@mail/model/model_field_command'; import { cleanSearchTerm } from '@mail/utils/utils'; function factory(dependencies) { @@ -142,14 +142,19 @@ function factory(dependencies) { }, { shadow: true } ); + if (!this.exists()) { + return; + } this.update({ searchResultCount: count, selectablePartners: insertAndReplace(partnersData.map(partnerData => this.messaging.models['mail.partner'].convertData(partnerData))), }); } finally { - this.update({ hasSearchRpcInProgress: false }); - if (this.hasPendingSearchRpc) { - this.searchPartnersToInvite(); + if (this.exists()) { + this.update({ hasSearchRpcInProgress: false }); + if (this.hasPendingSearchRpc) { + this.searchPartnersToInvite(); + } } } } @@ -175,9 +180,27 @@ function factory(dependencies) { return this.env._t("Invite to Channel"); } + /** + * @private + * @returns {FieldCommand} + */ + _computeThread() { + if (this.threadView && this.threadView.thread) { + return replace(this.threadView.thread); + } + if (this.chatWindow && this.chatWindow.thread) { + return replace(this.chatWindow.thread); + } + return clear(); + } + } ChannelInvitationForm.fields = { + chatWindow: one2one('mail.chat_window', { + inverse: 'channelInvitationForm', + readonly: true, + }), /** * States the OWL component of this channel invitation form. * Useful to be able to close it with popover trigger, or to know when @@ -240,8 +263,8 @@ function factory(dependencies) { * States the thread on which this list operates (if any). */ thread: many2one('mail.thread', { + compute: '_computeThread', readonly: true, - related: 'threadView.thread', required: true, }), /** @@ -252,7 +275,7 @@ function factory(dependencies) { readonly: true, }), }; - ChannelInvitationForm.identifyingFields = ['threadView']; + ChannelInvitationForm.identifyingFields = [['chatWindow', 'threadView']]; ChannelInvitationForm.modelName = 'mail.channel_invitation_form'; return ChannelInvitationForm; diff --git a/addons/mail/static/src/models/chat_window/chat_window.js b/addons/mail/static/src/models/chat_window/chat_window.js index 2120bb08292..b0f8647d8c6 100644 --- a/addons/mail/static/src/models/chat_window/chat_window.js +++ b/addons/mail/static/src/models/chat_window/chat_window.js @@ -15,7 +15,9 @@ function factory(dependencies) { _created() { super._created(); // Bind necessary until OWL supports arrow function in handlers: https://github.com/odoo/owl/issues/876 + this.onClickHideInviteForm = this.onClickHideInviteForm.bind(this); this.onClickHideMemberList = this.onClickHideMemberList.bind(this); + this.onClickShowInviteForm = this.onClickShowInviteForm.bind(this); this.onClickShowMemberList = this.onClickShowMemberList.bind(this); this.onFocusInNewMessageFormInput = this.onFocusInNewMessageFormInput.bind(this); } @@ -127,6 +129,16 @@ function factory(dependencies) { this.manager.swap(this, lastVisible); } + /** + * Handles click on the "stop adding users" button. + * + * @param {MouseEvent} ev + */ + onClickHideInviteForm(ev) { + markEventHandled(ev, 'ChatWindow.onClickCommand'); + this.update({ channelInvitationForm: clear() }); + } + /** * @param {MouseEvent} ev */ @@ -138,12 +150,33 @@ function factory(dependencies) { } } + /** + * Handles click on the "add users" button. + * + * @param {MouseEvent} ev + */ + onClickShowInviteForm(ev) { + markEventHandled(ev, 'ChatWindow.onClickCommand'); + this.update({ + channelInvitationForm: insertAndReplace({ + doFocusOnSearchInput: true, + }), + isMemberListOpened: false, + }); + if (!this.messaging.isCurrentUserGuest) { + this.channelInvitationForm.searchPartnersToInvite(); + } + } + /** * @param {MouseEvent} ev */ onClickShowMemberList(ev) { markEventHandled(ev, 'ChatWindow.onClickShowMemberList'); - this.update({ isMemberListOpened: true }); + this.update({ + channelInvitationForm: clear(), + isMemberListOpened: true, + }); } /** @@ -194,7 +227,18 @@ function factory(dependencies) { * @returns {boolean} */ _computeHasCallButtons() { - return this.thread && this.thread.rtcSessions.length === 0 && ['channel', 'chat', 'group'].includes(this.thread.channel_type); + return Boolean(this.thread) && this.thread.rtcSessions.length === 0 && ['channel', 'chat', 'group'].includes(this.thread.channel_type); + } + + /** + * @private + * @returns {boolean} + */ + _computeHasInviteFeature() { + return Boolean( + this.thread && this.thread.hasInviteFeature && + this.messaging && this.messaging.device && this.messaging.device.isMobile + ); } /** @@ -241,7 +285,7 @@ function factory(dependencies) { * @returns {boolean} */ _computeHasThreadView() { - return this.isVisible && !this.isFolded && !!this.thread; + return this.isVisible && !this.isFolded && !!this.thread && !this.isMemberListOpened && !this.channelInvitationForm; } /** @@ -368,6 +412,14 @@ function factory(dependencies) { } ChatWindow.fields = { + /** + * Determines the channel invitation form displayed by this chat window + * (if any). Only makes sense if hasInviteFeature is true. + */ + channelInvitationForm: one2one('mail.channel_invitation_form', { + inverse: 'chatWindow', + isCausal: true, + }), /** * Determines whether the buttons to start a RTC call should be displayed. */ @@ -375,6 +427,12 @@ function factory(dependencies) { default: false, compute: '_computeHasCallButtons', }), + /** + * States whether this chat window has the invite feature. + */ + hasInviteFeature: attr({ + compute: '_computeHasInviteFeature', + }), /** * Determines whether "new message form" should be displayed. */