From 985b7f37d748c4efa2cdcfcdb12e52a5daac6788 Mon Sep 17 00:00:00 2001 From: "Louis Wicket (wil)" Date: Tue, 28 Sep 2021 17:43:45 +0000 Subject: [PATCH] [IMP] mail: merge welcome and thread views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit will merge welcome and thread views in the same route and template. The aim is to make the user interacting with the page (by landing them on the welcome view first) so that the browser allows the page to play audio and to switch to full screen. closes odoo/odoo#77381 X-original-commit: 97ed683e3e7cc6b340bb78c4faa01a703a573f32 Signed-off-by: Sébastien Theys (seb) --- addons/mail/controllers/discuss.py | 117 ++++++++++----- .../discuss_public_view.js | 22 +++ .../discuss_public_view.xml | 19 +++ .../media_preview/media_preview.xml | 30 ++-- .../components/welcome_view/welcome_view.xml | 30 ++-- .../discuss_public_view.js | 106 ++++++++++++++ .../src/models/media_preview/media_preview.js | 20 ++- .../src/models/rtc_session/rtc_session.js | 3 + .../mail/static/src/models/thread/thread.js | 2 +- .../src/models/welcome_view/welcome_view.js | 137 +++++++++++++----- .../static/src/public/discuss_public_boot.js | 65 +++------ .../mail/views/discuss_public_templates.xml | 22 +-- 12 files changed, 400 insertions(+), 173 deletions(-) create mode 100644 addons/mail/static/src/components/discuss_public_view/discuss_public_view.js create mode 100644 addons/mail/static/src/components/discuss_public_view/discuss_public_view.xml create mode 100644 addons/mail/static/src/models/discuss_public_view/discuss_public_view.js diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index aa828d571fe..732929748c5 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -25,16 +25,39 @@ class DiscussController(http.Controller): '/chat/', '/chat//', ], methods=['GET'], type='http', auth='public') - def discuss_channel_from_token(self, create_token, channel_name=None, **kwargs): + def discuss_channel_chat_from_token(self, create_token, channel_name=None, **kwargs): + return self._response_discuss_channel_from_token(create_token=create_token, channel_name=channel_name) + + @http.route([ + '/meet/', + '/meet//', + ], methods=['GET'], type='http', auth='public') + def discuss_channel_meet_from_token(self, create_token, channel_name=None, **kwargs): + return self._response_discuss_channel_from_token(create_token=create_token, channel_name=channel_name, default_display_mode='video_full_screen') + + @http.route('/chat//', methods=['GET'], type='http', auth='public') + def discuss_channel_invitation(self, channel_id, invitation_token, **kwargs): + channel_sudo = request.env['mail.channel'].browse(channel_id).sudo().exists() + if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, invitation_token): + raise NotFound() + return self._response_discuss_channel_invitation(channel_sudo=channel_sudo) + + @http.route('/discuss/channel/', methods=['GET'], type='http', auth='public') + def discuss_channel(self, channel_id, **kwargs): + channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) + return self._response_discuss_public_channel_template(channel_sudo=channel_partner_sudo.channel_id) + + def _response_discuss_channel_from_token(self, create_token, channel_name=None, default_display_mode=False): if not request.env['ir.config_parameter'].sudo().get_param('mail.chat_from_token'): raise NotFound() channel_sudo = request.env['mail.channel'].sudo().search([('uuid', '=', create_token)]) if not channel_sudo: try: channel_sudo = channel_sudo.create({ - 'uuid': create_token, + 'default_display_mode': default_display_mode, 'name': channel_name or create_token, 'public': 'public', + 'uuid': create_token, }) except IntegrityError as e: if e.pgcode != UNIQUE_VIOLATION: @@ -43,50 +66,54 @@ class DiscussController(http.Controller): # commit the current transaction and get the channel. request.env.cr.commit() channel_sudo = channel_sudo.search([('uuid', '=', create_token)]) - return request.redirect(f'/chat/{channel_sudo.id}/{channel_sudo.uuid}') + return self._response_discuss_channel_invitation(channel_sudo=channel_sudo, is_channel_token_secret=False) - @http.route('/chat//', methods=['GET'], type='http', auth='public') - def discuss_channel_invitation(self, channel_id, invitation_token, **kwargs): - channel_sudo = request.env['mail.channel'].browse(int(channel_id)).sudo().exists() - if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, invitation_token): - raise NotFound() - if channel_sudo.env['mail.channel.partner']._get_as_sudo_from_request(request=request, channel_id=int(channel_id)): - return request.redirect(f'/discuss/channel/{channel_sudo.id}') + def _response_discuss_channel_invitation(self, channel_sudo, is_channel_token_secret=True): if channel_sudo.channel_type == 'chat': raise NotFound() - response = request.redirect(f'/discuss/channel/{channel_sudo.id}/welcome') - if not channel_sudo.env.user._is_public(): - channel_sudo.add_members([channel_sudo.env.user.partner_id.id]) - return response - guest = channel_sudo.env['mail.guest']._get_guest_from_request(request) - if not guest: - guest = channel_sudo.env['mail.guest'].create({ - 'country_id': channel_sudo.env['res.country'].search([('code', '=', request.session.get('geoip', {}).get('country_code'))], limit=1).id, - 'lang': get_lang(channel_sudo.env).code, - 'name': _("Guest"), - 'timezone': channel_sudo.env['mail.guest']._get_timezone_from_request(request), - }) + discuss_public_view_data = { + 'isChannelTokenSecret': is_channel_token_secret, + } + add_guest_cookie = False + if not channel_sudo.env['mail.channel.partner']._get_as_sudo_from_request(request=request, channel_id=channel_sudo.id): + if not channel_sudo.env.user._is_public(): + channel_sudo.add_members([channel_sudo.env.user.partner_id.id]) + else: + guest = channel_sudo.env['mail.guest']._get_guest_from_request(request) + if guest: + channel_sudo.add_members(guest_ids=[guest.id]) + else: + guest = channel_sudo.env['mail.guest'].create({ + 'country_id': channel_sudo.env['res.country'].search([('code', '=', request.session.get('geoip', {}).get('country_code'))], limit=1).id, + 'lang': get_lang(channel_sudo.env).code, + 'name': _("Guest"), + 'timezone': channel_sudo.env['mail.guest']._get_timezone_from_request(request), + }) + add_guest_cookie = True + discuss_public_view_data.update({ + 'shouldAddGuestAsMemberOnJoin': True, + 'shouldDisplayWelcomeViewInitially': True, + }) + channel_sudo = channel_sudo.with_context(guest=guest) + response = self._response_discuss_public_channel_template(channel_sudo=channel_sudo, discuss_public_view_data=discuss_public_view_data) + if add_guest_cookie: # Discuss Guest ID: every route in this file will make use of it to authenticate # the guest through `_get_as_sudo_from_request` or `_get_as_sudo_from_request_or_raise`. expiration_date = datetime.now() + timedelta(days=365) response.set_cookie(guest._cookie_name, f"{guest.id}{guest._cookie_separator}{guest.access_token}", httponly=True, expires=expiration_date) - channel_sudo.add_members(guest_ids=[guest.id]) return response - @http.route('/discuss/channel/', methods=['GET'], type='http', auth='public') - def discuss_channel(self, channel_id, **kwargs): - channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) + def _response_discuss_public_channel_template(self, channel_sudo, discuss_public_view_data=None): + discuss_public_view_data = discuss_public_view_data or {} return request.render('mail.discuss_public_channel_template', { - 'channel_sudo': channel_partner_sudo.channel_id, - 'session_info': channel_partner_sudo.env['ir.http'].session_info(), - }) - - @http.route('/discuss/channel//welcome', methods=['GET'], type='http', auth='public') - def discuss_channel_welcome(self, channel_id): - channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) - return request.render('mail.discuss_public_welcome_template', { - 'channel_sudo': channel_partner_sudo.channel_id, - 'session_info': channel_partner_sudo.env['ir.http'].session_info(), + 'data': { + 'channelData': channel_sudo.channel_info()[0], + 'discussPublicViewData': dict({ + 'channel': [('insert', {'id': channel_sudo.id, 'model': 'mail.channel'})], + 'shouldDisplayWelcomeViewInitially': channel_sudo.default_display_mode == 'video_full_screen', + }, **discuss_public_view_data), + }, + 'session_info': channel_sudo.env['ir.http'].session_info(), }) # -------------------------------------------------------------------------- @@ -303,6 +330,22 @@ class DiscussController(http.Controller): # Channel API # -------------------------------------------------------------------------- + @http.route('/mail/channel/add_guest_as_member', methods=['POST'], type='json', auth='public') + def mail_channel_add_guest_as_member(self, channel_id, channel_uuid, **kwargs): + channel_sudo = request.env['mail.channel'].browse(int(channel_id)).sudo().exists() + if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, channel_uuid): + raise NotFound() + if channel_sudo.channel_type == 'chat': + raise NotFound() + guest = channel_sudo.env['mail.guest']._get_guest_from_request(request) + # Only guests should take this route. + if not guest: + raise NotFound() + channel_partner = channel_sudo.env['mail.channel.partner']._get_as_sudo_from_request(request=request, channel_id=channel_id) + # Do not add the guest to channel members if they are already member. + if not channel_partner: + channel_sudo.add_members(guest_ids=[guest.id]) + @http.route('/mail/channel/messages', methods=['POST'], type='json', auth='public') def mail_channel_messages(self, channel_id, max_id=None, min_id=None, limit=30, **kwargs): channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) @@ -434,7 +477,7 @@ class DiscussController(http.Controller): if session and session.guest_id == guest: session._update_and_broadcast(values) return - raise NotFound() + return session = request.env['mail.channel.rtc.session'].sudo().browse(int(session_id)).exists() if session and session.partner_id == request.env.user.partner_id: session._update_and_broadcast(values) diff --git a/addons/mail/static/src/components/discuss_public_view/discuss_public_view.js b/addons/mail/static/src/components/discuss_public_view/discuss_public_view.js new file mode 100644 index 00000000000..1cb71c313b8 --- /dev/null +++ b/addons/mail/static/src/components/discuss_public_view/discuss_public_view.js @@ -0,0 +1,22 @@ +/** @odoo-module **/ + +import { registerMessagingComponent } from '@mail/utils/messaging_component'; + +const { Component } = owl; + +class DiscussPublicView extends Component { + + /** + * @returns {mail.discuss_public_view} + */ + get discussPublicView() { + return this.messaging && this.messaging.models['mail.discuss_public_view'].get(this.props.localId); + } +} + +Object.assign(DiscussPublicView, { + props: { localId: String }, + template: 'mail.DiscussPublicView', +}); + +registerMessagingComponent(DiscussPublicView); diff --git a/addons/mail/static/src/components/discuss_public_view/discuss_public_view.xml b/addons/mail/static/src/components/discuss_public_view/discuss_public_view.xml new file mode 100644 index 00000000000..9772480c7b8 --- /dev/null +++ b/addons/mail/static/src/components/discuss_public_view/discuss_public_view.xml @@ -0,0 +1,19 @@ + + + +
+ + + + +
+
+
diff --git a/addons/mail/static/src/components/media_preview/media_preview.xml b/addons/mail/static/src/components/media_preview/media_preview.xml index 0a008e27eb6..1c0bfb0ef39 100644 --- a/addons/mail/static/src/components/media_preview/media_preview.xml +++ b/addons/mail/static/src/components/media_preview/media_preview.xml @@ -3,20 +3,22 @@
-
diff --git a/addons/mail/static/src/components/welcome_view/welcome_view.xml b/addons/mail/static/src/components/welcome_view/welcome_view.xml index 2041d8045c5..e8781cfb28e 100644 --- a/addons/mail/static/src/components/welcome_view/welcome_view.xml +++ b/addons/mail/static/src/components/welcome_view/welcome_view.xml @@ -3,21 +3,23 @@
-

You've been invited to a meeting!

-

-
- -
- - - - - -

Logged as

-
-
-

+
diff --git a/addons/mail/static/src/models/discuss_public_view/discuss_public_view.js b/addons/mail/static/src/models/discuss_public_view/discuss_public_view.js new file mode 100644 index 00000000000..bc6ef17ba7c --- /dev/null +++ b/addons/mail/static/src/models/discuss_public_view/discuss_public_view.js @@ -0,0 +1,106 @@ +/** @odoo-module **/ + +import { attr, one2one } from '@mail/model/model_field'; +import { registerNewModel } from '@mail/model/model_core'; +import { clear, create, link } from '@mail/model/model_field_command'; + +function factory(dependencies) { + + class DiscussPublicView extends dependencies['mail.model'] { + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + /** + * Creates and displays the thread view and clears the welcome view. + */ + async switchToThreadView() { + this.update({ + threadViewer: create({ + extraClass: 'flex-grow-1', + hasMemberList: true, + hasThreadView: true, + hasTopbar: true, + thread: link(this.channel), + }), + welcomeView: clear(), + }); + if (this.isChannelTokenSecret) { + // Change the URL to avoid leaking the invitation link. + window.history.replaceState(window.history.state, null, `/discuss/channel/${this.channel.id}`); + } + if (this.channel.defaultDisplayMode === 'video_full_screen') { + await this.channel.toggleCall({ startWithVideo: true }); + await this.threadView.rtcCallViewer.activateFullScreen(); + } + } + + /** + * Creates and displays the welcome view and clears the thread viewer. + */ + switchToWelcomeView() { + this.update({ + threadViewer: clear(), + welcomeView: create({ + channel: link(this.channel), + isDoFocusGuestNameInput: true, + originalGuestName: this.messaging.currentGuest && this.messaging.currentGuest.name, + pendingGuestName: this.messaging.currentGuest && this.messaging.currentGuest.name, + }), + }); + if (this.channel.defaultDisplayMode === 'video_full_screen') { + this.welcomeView.mediaPreview.enableMicrophone(); + this.welcomeView.mediaPreview.enableVideo(); + } + } + + } + + DiscussPublicView.fields = { + /** + * States the channel linked to this discuss public view. + */ + channel: one2one('mail.thread', { + readonly: true, + required: true, + }), + isChannelTokenSecret: attr({ + default: true, + }), + shouldAddGuestAsMemberOnJoin: attr({ + default: false, + readonly: true, + }), + shouldDisplayWelcomeViewInitially: attr({ + default: false, + readonly: true, + }), + /** + * States the thread view linked to this discuss public view. + */ + threadView: one2one('mail.thread_view', { + readonly: true, + related: 'threadViewer.threadView', + }), + /** + * States the thread viewer linked to this discuss public view. + */ + threadViewer: one2one('mail.thread_viewer', { + isCausal: true, + }), + /** + * States the welcome view linked to this discuss public view. + */ + welcomeView: one2one('mail.welcome_view', { + inverse: 'discussPublicView', + isCausal: true, + }), + }; + + DiscussPublicView.modelName = 'mail.discuss_public_view'; + + return DiscussPublicView; +} + +registerNewModel('mail.discuss_public_view', factory); diff --git a/addons/mail/static/src/models/media_preview/media_preview.js b/addons/mail/static/src/models/media_preview/media_preview.js index b95ae62d672..a9cf92f9922 100644 --- a/addons/mail/static/src/models/media_preview/media_preview.js +++ b/addons/mail/static/src/models/media_preview/media_preview.js @@ -69,9 +69,13 @@ function factory(dependencies) { if (!this.doesBrowserSupportMediaDevices) { return; } - const audioStream = await navigator.mediaDevices.getUserMedia({ audio: true }); - this.update({ audioStream }); - this.audioRef.el.srcObject = this.audioStream; + try { + const audioStream = await navigator.mediaDevices.getUserMedia({ audio: true }); + this.update({ audioStream }); + this.audioRef.el.srcObject = this.audioStream; + } catch { + // TODO: display popup asking the user to re-enable their mic + } } /** @@ -83,9 +87,13 @@ function factory(dependencies) { if (!this.doesBrowserSupportMediaDevices) { return; } - const videoStream = await navigator.mediaDevices.getUserMedia({ video: true }); - this.update({ videoStream }); - this.videoRef.el.srcObject = this.videoStream; + try { + const videoStream = await navigator.mediaDevices.getUserMedia({ video: true }); + this.update({ videoStream }); + this.videoRef.el.srcObject = this.videoStream; + } catch { + // TODO: display popup asking the user to re-enable their camera + } } /** diff --git a/addons/mail/static/src/models/rtc_session/rtc_session.js b/addons/mail/static/src/models/rtc_session/rtc_session.js index 5d72a29e8ef..8ef650820ab 100644 --- a/addons/mail/static/src/models/rtc_session/rtc_session.js +++ b/addons/mail/static/src/models/rtc_session/rtc_session.js @@ -171,6 +171,9 @@ function factory(dependencies) { } this.update(data); this._debounce(async () => { + if (!this.exists()) { + return; + } await this.async(() => { this.env.services.rpc( { diff --git a/addons/mail/static/src/models/thread/thread.js b/addons/mail/static/src/models/thread/thread.js index 57cb826d119..5c13d56baa0 100644 --- a/addons/mail/static/src/models/thread/thread.js +++ b/addons/mail/static/src/models/thread/thread.js @@ -2079,10 +2079,10 @@ function factory(dependencies) { futureActivities: one2many('mail.activity', { compute: '_computeFutureActivities', }), - guestMembers: many2many('mail.guest'), group_based_subscription: attr({ default: false, }), + guestMembers: many2many('mail.guest'), /** * States whether `this` has activities (`mail.activity.mixin` server side). */ diff --git a/addons/mail/static/src/models/welcome_view/welcome_view.js b/addons/mail/static/src/models/welcome_view/welcome_view.js index 94a643cce9c..2abb3bf61c6 100644 --- a/addons/mail/static/src/models/welcome_view/welcome_view.js +++ b/addons/mail/static/src/models/welcome_view/welcome_view.js @@ -1,13 +1,12 @@ /** @odoo-module **/ import { attr, one2one } from '@mail/model/model_field'; -import { browser } from "@web/core/browser/browser"; import { create } from '@mail/model/model_field_command'; import { registerNewModel } from '@mail/model/model_core'; function factory(dependencies) { - const getNextGuestNameInputId = (function() { + const getNextGuestNameInputId = (function () { let id = 0; return () => ++id; })(); @@ -31,9 +30,9 @@ function factory(dependencies) { /** * @static - * @param {string} name + * @param {string} name */ - static async updateGuestNameServerSide(name) { + static async performRpcGuestUpdateName(name) { await this.env.services.rpc({ route: '/mail/guest/update_name', params: { name }, @@ -41,10 +40,24 @@ function factory(dependencies) { } /** - * @param {MouseEvent} ev + * Updates guest if needed then displays the thread view instead of the + * welcome view. */ - async onClickJoinButton(ev) { - this.updateGuestNameIfAnyThenJoinChannel(); + async joinChannel() { + if (this.hasGuestNameChanged) { + await this.messaging.models['mail.welcome_view'].performRpcGuestUpdateName(this.pendingGuestName.trim()); + } + if (this.discussPublicView.shouldAddGuestAsMemberOnJoin) { + await this.performRpcAddGuestAsMember(); + } + this.discussPublicView.switchToThreadView(); + } + + /** + * @param {MouseEvent} ev + */ + onClickJoinButton(ev) { + this.joinChannel(); } /** @@ -55,43 +68,70 @@ function factory(dependencies) { } /** - * @param {KeyboardEvent} ev + * @param {KeyboardEvent} ev */ onInputGuestNameInput(ev) { this._updateGuestNameWithInputValue(); } /** - * @param {KeyboardEvent} ev + * @param {KeyboardEvent} ev */ onKeydownGuestNameInput(ev) { if (ev.key === 'Enter') { - this.updateGuestNameIfAnyThenJoinChannel(); + this.joinChannel(); } } /** - * Redirects users to the related channel. If the current user is a - * guest, first updates their username with the value of guestNameInput. + * Adds the current guest to members of the channel linked to this + * welcome view. */ - async updateGuestNameIfAnyThenJoinChannel() { - if (this.messaging.currentGuest) { - await this.messaging.models['mail.welcome_view'].updateGuestNameServerSide(this.pendingGuestName.trim()); - } - browser.location.href = `/discuss/channel/${this.channel.id}`; + async performRpcAddGuestAsMember() { + await this.env.services.rpc({ + route: '/mail/channel/add_guest_as_member', + params: { + channel_id: this.channel.id, + channel_uuid: this.channel.uuid, + }, + }); } //---------------------------------------------------------------------- // Private //---------------------------------------------------------------------- + /** + * @private + * @returns {string} + */ + _computeGuestNameInputUniqueId() { + return `o_WelcomeView_guestNameInput_${getNextGuestNameInputId()}`; + } + + /** + * @private + * @returns {boolean} + */ + _computeHasGuestNameChanged() { + return Boolean(this.messaging.currentGuest && this.originalGuestName !== this.pendingGuestName); + } + + /** + * @private + * @returns {boolean} + */ + _computeIsJoinButtonDisabled() { + return Boolean(this.messaging.currentGuest && this.pendingGuestName.trim() === ''); + } + /** * @private */ _handleFocus() { if (this.isDoFocusGuestNameInput) { if (!this.guestNameInputRef.el) { - return + return; } this.update({ isDoFocusGuestNameInput: false }); this.guestNameInputRef.el.focus(); @@ -102,40 +142,59 @@ function factory(dependencies) { } /** + * Updates `pendingGuestName` with the value of the input element + * referred by `guestNameInputRef`. + * * @private */ _updateGuestNameWithInputValue() { this.update({ pendingGuestName: this.guestNameInputRef.el.value }); } - /** - * @private - * @returns {boolean} - */ - _computeIsJoinButtonDisabled() { - return Boolean(this.messaging.currentGuest && !this.pendingGuestName.trim()); - } - } WelcomeView.fields = { /** - * The channel to redirect to once the user clicks on the 'joinButton'. + * States the channel to redirect to once the user clicks on the + * 'joinButton'. */ channel: one2one('mail.thread', { + readonly: true, required: true, }), /** - * Used as a value for `id`, `for`, and `name` attributes of the guest - * name input and its label. Necessary to ensure the uniqueness. + * States discuss public view on which this welcome view is displayed. */ - guestNameInputUniqueId: attr({ - default: `o_WelcomeView_guestNameInput_${getNextGuestNameInputId()}`, + discussPublicView: one2one('mail.discuss_public_view', { + inverse: 'welcomeView', + readonly: true, + required: true, }), /** - * Ref the to input element containing the 'pendingGuestName'. + * States the OWL ref the to input element containing the + * 'pendingGuestName'. */ guestNameInputRef: attr(), + /** + * States the value to use for `id`, `for`, and `name` attributes of + * the guest name input and its label. + * + * Necessary to ensure the uniqueness. + */ + guestNameInputUniqueId: attr({ + compute: '_computeGuestNameInputUniqueId', + readonly: true, + }), + /** + * Determines whether the guest's name has been updated. + * + * Useful to determine whether a RPC should be done to update the name + * server side. + */ + hasGuestNameChanged: attr({ + compute: '_computeHasGuestNameChanged', + readonly: true, + }), /** * Determines whether the 'guestNameInput' should be focused the next * time the component is updated. @@ -143,7 +202,7 @@ function factory(dependencies) { isDoFocusGuestNameInput: attr(), /** * Determines whether the 'joinButton' is disabled. - * + * * Shall be disabled when 'pendingGuestName' is an empty string while * the current user is a guest. */ @@ -151,7 +210,7 @@ function factory(dependencies) { compute: '_computeIsJoinButtonDisabled' }), /** - * The MediaPreview linked to the current WelcomeView. + * States the media preview embedded in this welcome view. */ mediaPreview: one2one('mail.media_preview', { default: create(), @@ -160,8 +219,14 @@ function factory(dependencies) { required: true, }), /** - * The value of the 'guestNameInput'. - * + * States the name the guest had when landing on the welcome view. + * + * Useful to determine whether the name has changed. + */ + originalGuestName: attr(), + /** + * Determines the value of the 'guestNameInput'. + * * Will be used to update the current guest's name when joining the * channel by clicking on the 'joinButton'. */ diff --git a/addons/mail/static/src/public/discuss_public_boot.js b/addons/mail/static/src/public/discuss_public_boot.js index 94afa283482..26142db85ea 100644 --- a/addons/mail/static/src/public/discuss_public_boot.js +++ b/addons/mail/static/src/public/discuss_public_boot.js @@ -1,6 +1,7 @@ /** @odoo-module **/ -import { insert, link } from '@mail/model/model_field_command'; +import { data } from 'mail.discuss_public_channel_template'; + import { MessagingService } from '@mail/services/messaging/messaging'; import { getMessagingComponent } from '@mail/utils/messaging_component'; @@ -25,7 +26,7 @@ import * as legacySession from 'web.session'; owl.Component.env = legacyEnv; -export async function boot() { +(async function boot() { await owl.utils.whenReady(); owl.config.mode = owl.Component.env.isDebug() ? 'dev' : 'prod'; AbstractService.prototype.deployServices(owl.Component.env); @@ -60,51 +61,21 @@ export async function boot() { }, })); await owl.mount(MainComponentsContainer, { env, target: document.body }); + createAndMountDiscussPublicView(); +})(); - async function createThreadViewFromChannelData(channelData) { - const messaging = await owl.Component.env.services.messaging.get(); - const threadViewer = messaging.models['mail.thread_viewer'].create({ - extraClass: 'flex-grow-1', - hasMemberList: true, - hasThreadView: true, - hasTopbar: true, - thread: insert(messaging.models['mail.thread'].convertData(channelData)), - }); - const ThreadView = getMessagingComponent('ThreadView'); - const threadViewComponent = new ThreadView(null, { - composerAttachmentsDetailsMode: 'card', - hasComposer: true, - hasComposerThreadTyping: true, - hasSquashCloseMessages: true, - threadViewLocalId: threadViewer.threadView.localId, - }); - await threadViewComponent.mount(document.body); - if (threadViewer.thread.defaultDisplayMode === 'video_full_screen') { - await threadViewer.thread.toggleCall({ startWithVideo: true }); - // TODO full screen not possible until the user actually makes an action on the page - } +async function createAndMountDiscussPublicView() { + const messaging = await owl.Component.env.services.messaging.get(); + messaging.models['mail.thread'].insert(messaging.models['mail.thread'].convertData(data.channelData)); + const discussPublicView = messaging.models['mail.discuss_public_view'].create(data.discussPublicViewData); + if (discussPublicView.shouldDisplayWelcomeViewInitially) { + discussPublicView.switchToWelcomeView(); + } else { + discussPublicView.switchToThreadView(); } - - async function createWelcomeView(channelData) { - const messaging = await owl.Component.env.services.messaging.get(); - const channel = messaging.models['mail.thread'].insert( - messaging.models['mail.thread'].convertData(channelData) - ); - const WelcomeView = getMessagingComponent('WelcomeView'); - const welcomeView = messaging.models['mail.welcome_view'].create({ - channel: link(channel), - isDoFocusGuestNameInput: true, - pendingGuestName: messaging.currentGuest && messaging.currentGuest.name, - }); - const welcomeViewComponent = new WelcomeView(null, { - localId: welcomeView.localId, - }); - await welcomeViewComponent.mount(document.body); - if (welcomeView.channel.defaultDisplayMode === 'video_full_screen') { - welcomeView.mediaPreview.enableMicrophone(); - welcomeView.mediaPreview.enableVideo(); - } - } - - return { createThreadViewFromChannelData, createWelcomeView }; + const DiscussPublicView = getMessagingComponent('DiscussPublicView'); + const discussPublicViewComponent = new DiscussPublicView(null, { + localId: discussPublicView.localId, + }); + await discussPublicViewComponent.mount(document.body); } diff --git a/addons/mail/views/discuss_public_templates.xml b/addons/mail/views/discuss_public_templates.xml index 6f7af7ae92a..c9b499f6cd8 100644 --- a/addons/mail/views/discuss_public_templates.xml +++ b/addons/mail/views/discuss_public_templates.xml @@ -38,24 +38,10 @@ - - - - -