[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:
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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',
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user