[REF] use ChannelMember in CallParticipantCard model

part of task-2692836

closes odoo/odoo#95418

Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Thanh Dodeur
2022-07-27 02:18:09 +02:00
parent a396f791da
commit 0efcb55c6f
6 changed files with 70 additions and 80 deletions
@@ -6,10 +6,10 @@
<div class="o_CallParticipantCard position-relative o_cursor_pointer d-flex flex-column align-items-center justify-content-center mh-100 mw-100 p-1 rounded-1"
t-att-class="{
'o-isTalking': !callParticipantCard.isMinimized and callParticipantCard.isTalking,
'o-isInvitation opacity-50': callParticipantCard.invitedMember,
'o-isInvitation opacity-50': !callParticipantCard.rtcSession,
}"
t-att-title="callParticipantCard.name"
t-att-aria-label="callParticipantCard.name"
t-att-title="callParticipantCard.channelMember.persona.name"
t-att-aria-label="callParticipantCard.channelMember.persona.name"
t-attf-class="{{ className }}"
t-on-click="callParticipantCard.onClick"
t-on-contextmenu="callParticipantCard.onContextMenu"
@@ -24,10 +24,10 @@
<img alt="Avatar"
t-att-class="{
'o-isTalking': callParticipantCard.isTalking,
'o-isInvitation': callParticipantCard.invitedMember,
'o-isInvitation': !callParticipantCard.rtcSession,
}"
class="o_CallParticipantCard_avatarImage h-100 rounded-circle border-5 o_object_fit_cover"
t-att-src="callParticipantCard.avatarUrl"
t-att-src="callParticipantCard.channelMember.avatarUrl"
draggable="false"
/>
</div>
@@ -37,7 +37,7 @@
<!-- overlay -->
<span class="o_CallParticipantCard_overlay o_CallParticipantCard_overlayBottom position-absolute bottom-0 start-0 d-flex overflow-hidden">
<t t-if="!callParticipantCard.isMinimized">
<span class="o_CallParticipantCard_name p-1 rounded-1 bg-black-75 text-white text-truncate" t-esc="callParticipantCard.name"/>
<span class="o_CallParticipantCard_name p-1 rounded-1 bg-black-75 text-white text-truncate" t-esc="callParticipantCard.channelMember.persona.name"/>
</t>
<t t-if="callParticipantCard.rtcSession.isScreenSharingOn and callParticipantCard.isMinimized and !callParticipantCard.rtcSession.channel.rtc">
<small class="o_CallParticipantCard_liveIndicator o-isMinimized rounded-pill text-bg-danger d-flex align-items-center fw-bolder" title="live" aria-label="live">
@@ -9,7 +9,7 @@ import { sprintf } from '@web/core/utils/strings';
registerModel({
name: 'CallParticipantCard',
identifyingFields: [['rtcSession', 'invitedMember'], ['callViewAsMainCard', 'callViewAsTile']],
identifyingFields: ['channelMember', ['callViewAsMainCard', 'callViewAsTile']],
recordMethods: {
/**
* @param {Event} ev
@@ -32,12 +32,12 @@ registerModel({
}
return;
}
const channel = this.channel;
const channel = this.channelMember.channel.thread;
const channelData = await this.messaging.rpc(({
route: '/mail/rtc/channel/cancel_call_invitation',
params: {
channel_id: this.channel.id,
member_ids: this.invitedMember && [this.invitedMember.id],
channel_id: channel.id,
member_ids: [this.channelMember.id],
},
}));
if (!channel.exists()) {
@@ -66,21 +66,6 @@ registerModel({
}
this.volumeMenuAnchorRef.el.click();
},
/**
* @private
* @returns {string}
*/
_computeAvatarUrl() {
if (!this.channel) {
return;
}
if (this.rtcSession) {
return this.rtcSession.channelMember.avatarUrl;
}
if (this.invitedMember) {
return this.invitedMember.avatarUrl;
}
},
/**
* @private
* @returns {mail.callView}
@@ -98,7 +83,7 @@ registerModel({
* @returns {boolean}
*/
_computeHasConnectionInfo() {
return Boolean(this.rtcSession && this.env.debug && this.channel.rtc);
return Boolean(this.rtcSession && this.env.debug && this.channelMember.channel.thread.rtc);
},
/**
* @private
@@ -106,12 +91,12 @@ registerModel({
*/
_computeInboundConnectionTypeText() {
if (!this.rtcSession || !this.rtcSession.remoteCandidateType) {
return sprintf(this.env._t('From %s: no connection'), this.name);
return sprintf(this.env._t('From %s: no connection'), this.channelMember.persona.name);
}
return sprintf(
this.env._t('From %(name)s: %(candidateType)s (%(protocol)s)'), {
candidateType: this.rtcSession.remoteCandidateType,
name: this.name,
name: this.channelMember.persona.name,
protocol: this.messaging.rtc.protocolsByCandidateTypes[this.rtcSession.remoteCandidateType],
},
);
@@ -130,30 +115,18 @@ registerModel({
_computeIsTalking() {
return Boolean(this.rtcSession && this.rtcSession.isTalking && !this.rtcSession.isMute);
},
/**
* @private
* @returns {string}
*/
_computeName() {
if (this.rtcSession) {
return this.rtcSession.channelMember.persona.name;
}
if (this.invitedMember) {
return this.invitedMember.name;
}
},
/**
* @private
* @returns {string}
*/
_computeOutboundConnectionTypeText() {
if (!this.rtcSession || !this.rtcSession.localCandidateType) {
return sprintf(this.env._t('To %s: no connection'), this.name);
return sprintf(this.env._t('To %s: no connection'), this.channelMember.persona.name);
}
return sprintf(
this.env._t('To %(name)s: %(candidateType)s (%(protocol)s)'), {
candidateType: this.rtcSession.localCandidateType,
name: this.name,
name: this.channelMember.persona.name,
protocol: this.messaging.rtc.protocolsByCandidateTypes[this.rtcSession.localCandidateType],
},
);
@@ -170,17 +143,10 @@ registerModel({
},
},
fields: {
/**
* The relative url of the image that represents the card.
*/
avatarUrl: attr({
compute: '_computeAvatarUrl',
}),
/**
* The channel of the call.
*/
channel: one('Thread', {
channelMember: one('ChannelMember', {
inverse: 'callParticipantCards',
required: true,
readonly: true,
}),
/**
* Determines whether or not we show the connection info.
@@ -194,9 +160,6 @@ registerModel({
inboundConnectionTypeText: attr({
compute: '_computeInboundConnectionTypeText',
}),
invitedMember: one('ChannelMember', {
readonly: true,
}),
/**
* Determines if this card has to be displayed in a minimized form.
*/
@@ -211,13 +174,6 @@ registerModel({
default: false,
compute: '_computeIsTalking',
}),
/**
* The name of the rtcSession or the invited partner.
*/
name: attr({
default: 'Anonymous',
compute: '_computeName',
}),
/**
* The text describing the outbound ice connection candidate type.
*/
@@ -245,12 +201,9 @@ registerModel({
inverse: 'tileParticipantCards',
readonly: true,
}),
/**
* If set, this card represents a rtcSession.
*/
rtcSession: one('RtcSession', {
related: 'channelMember.rtcSession',
inverse: 'callParticipantCards',
readonly: true,
}),
callParticipantVideoView: one('CallParticipantVideoView', {
compute: '_computeCallParticipantVideoView',
+5 -12
View File
@@ -115,8 +115,7 @@ registerModel({
return clear();
}
return insert({
rtcSession: replace(this.activeRtcSession),
channel: replace(this.channel),
channelMember: replace(this.activeRtcSession.channelMember),
});
},
/**
@@ -128,6 +127,7 @@ registerModel({
},
/**
* @private
* @returns {FieldCommand}
*/
_computeTileParticipantCards() {
if (!this.threadView) {
@@ -137,19 +137,12 @@ registerModel({
return clear();
}
const tileCards = [];
for (const rtcSession of this.channel.rtcSessions) {
if (this.filterVideoGrid && !rtcSession.videoStream) {
for (const channelMember of this.channel.channel.callParticipants) {
if (this.filterVideoGrid && !channelMember.isStreaming) {
continue;
}
tileCards.push({
rtcSession: replace(rtcSession),
channel: replace(this.channel),
});
}
for (const member of this.channel.invitedMembers) {
tileCards.push({
invitedMember: replace(member),
channel: replace(this.channel),
channelMember: replace(channelMember),
});
}
return insertAndReplace(tileCards);
+26 -1
View File
@@ -2,7 +2,7 @@
import { registerModel } from '@mail/model/model_core';
import { attr, one, many } from '@mail/model/model_field';
import { insertAndReplace } from '@mail/model/model_field_command';
import { insertAndReplace, replace } from '@mail/model/model_field_command';
registerModel({
name: 'Channel',
@@ -29,6 +29,17 @@ registerModel({
_computeAreAllMembersLoaded() {
return this.memberCount === this.channelMembers.length;
},
/**
* @private
* @returns {FieldCommand}
*/
_computeCallParticipants() {
const callParticipants = this.thread.invitedMembers;
for (const rtcSession of this.thread.rtcSessions) {
callParticipants.push(rtcSession.channelMember);
}
return replace(callParticipants);
},
/**
* @private
* @returns {FieldCommand}
@@ -46,6 +57,16 @@ registerModel({
_computeUnknownMemberCount() {
return this.memberCount - this.channelMembers.length;
},
/**
* @private
* @returns {Array[]}
*/
_sortCallParticipants() {
return [
['truthy-first', 'rtcSession'],
['smaller-first', 'rtcSession.id'],
];
},
/**
* @private
* @returns {Array[]}
@@ -61,6 +82,10 @@ registerModel({
areAllMembersLoaded: attr({
compute: '_computeAreAllMembersLoaded',
}),
callParticipants: many('ChannelMember', {
compute: '_computeCallParticipants',
sort: '_sortCallParticipants',
}),
channelMembers: many('ChannelMember', {
inverse: 'channel',
isCausal: true,
@@ -47,11 +47,22 @@ registerModel({
}
return clear();
},
/**
* @private
* @returns {boolean}
*/
_computeIsStreaming() {
return Boolean(this.rtcSession && this.rtcSession.videoStream);
},
},
fields: {
avatarUrl: attr({
compute: '_computeAvatarUrl',
}),
callParticipantCards: many('CallParticipantCard', {
inverse: 'channelMember',
isCausal: true,
}),
channel: one('Channel', {
inverse: 'channelMembers',
readonly: true,
@@ -73,10 +84,16 @@ registerModel({
readonly: true,
required: true,
}),
isStreaming: attr({
compute: '_computeIsStreaming',
}),
persona: one('Persona', {
inverse: 'channelMembers',
readonly: true,
required: true,
}),
rtcSession: one('RtcSession', {
inverse: 'channelMember',
}),
},
});
+3 -1
View File
@@ -365,7 +365,9 @@ registerModel({
channel: one('Thread', {
inverse: 'rtcSessions',
}),
channelMember: one('ChannelMember'),
channelMember: one('ChannelMember', {
inverse: 'rtcSession',
}),
connectionRecoveryTimeout: attr(),
/**
* State of the connection with this session, uses RTCPeerConnection.iceConnectionState