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 @@ - - - - -