[REF] mail: separate the tile model based on the parent view
Before this commit, the `callParticipantCard` model was used separately for both the main session and the multi-tile views (`CallSidebarView`/`CallMainView`), this commit makes so that each multi-tile view has its own list of tiles. part of task-2692836 closes odoo/odoo#96868 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -6,10 +6,6 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.o_CallMainView_mainParticipantContainer {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.o_CallMainView_gridParticipantCard {
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
@@ -30,10 +26,6 @@
|
||||
// Style
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
.o_CallMainView_mainParticipantContainer {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.o_CallMainView_sidebarButton {
|
||||
color: white;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
|
||||
@@ -3,36 +3,28 @@
|
||||
|
||||
<t t-name="mail.CallMainView" owl="1">
|
||||
<t t-if="callMainView">
|
||||
<div class="o_CallMainView d-flex flex-grow-1 flex-column align-items-center justify-content-center" t-ref="root" t-on-mouseleave="callMainView.onMouseleave">
|
||||
<div class="o_CallMainView d-flex flex-grow-1 flex-column align-items-center justify-content-center position-relative bg-black-50" t-ref="root" t-on-mouseleave="callMainView.onMouseleave">
|
||||
<t t-set="dummy" t-value="messaging and messaging.device and messaging.device.globalWindowInnerHeight and messaging.device.globalWindowInnerWidth"/>
|
||||
|
||||
<div class="o_CallMainView_participantContainer d-flex justify-content-between w-100 h-100 overflow-hidden" t-on-click="callMainView.onClick" t-on-mousemove="callMainView.onMouseMove">
|
||||
<t t-if="callMainView.callView.mainParticipantCard">
|
||||
<div class="o_CallMainView_mainParticipantContainer d-flex flex-grow-1 justify-content-center position-relative mw-100 mh-100">
|
||||
<CallParticipantCard className="'o_CallMainView_participantCard'" record="callMainView.callView.mainParticipantCard"/>
|
||||
<t t-if="callMainView.showOverlay and !callMainView.callView.threadView.compact">
|
||||
<i t-if="callMainView.callView.hasSidebar" class="o_CallMainView_sidebarButton o_cursor_pointer position-absolute fa fa-arrow-right" title="Hide sidebar" t-on-click="callMainView.onClickHideSidebar"/>
|
||||
<i t-else="" class="o_CallMainView_sidebarButton o_cursor_pointer position-absolute fa fa-arrow-left" title="Show sidebar" t-on-click="callMainView.onClickShowSidebar"/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-elif="callMainView.callView.tileParticipantCards.length > 0">
|
||||
<div
|
||||
class="o_CallMainView_grid d-flex align-items-center overflow-hidden h-100 w-100 flex-wrap justify-content-center"
|
||||
t-ref="tileContainer"
|
||||
t-attf-style="--height:{{callMainView.tileHeight}}px; --width:{{callMainView.tileWidth}}px;"
|
||||
>
|
||||
<t t-foreach="callMainView.callView.tileParticipantCards" t-as="participantCard" t-key="'grid_tile_'+participantCard.localId">
|
||||
<CallParticipantCard
|
||||
className="'o_CallMainView_gridParticipantCard'"
|
||||
record="participantCard"
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
<div
|
||||
class="o_CallMainView_grid d-flex align-items-center overflow-hidden h-100 w-100 flex-wrap justify-content-center"
|
||||
t-attf-style="--height:{{callMainView.tileHeight}}px; --width:{{callMainView.tileWidth}}px;"
|
||||
t-on-click="callMainView.onClick"
|
||||
t-on-mousemove="callMainView.onMouseMove"
|
||||
t-ref="tileContainer"
|
||||
>
|
||||
<t t-foreach="callMainView.mainTiles" t-as="tile" t-key="'grid_tile_'+tile.localId">
|
||||
<CallParticipantCard
|
||||
className="'o_CallMainView_gridParticipantCard'"
|
||||
record="tile.participantCard"
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<t t-if="callMainView.hasSidebarButton">
|
||||
<i t-if="callMainView.callView.isSidebarOpen" class="o_CallMainView_sidebarButton o_cursor_pointer position-absolute fa fa-arrow-right" title="Hide sidebar" t-on-click="callMainView.onClickHideSidebar"/>
|
||||
<i t-else="" class="o_CallMainView_sidebarButton o_cursor_pointer position-absolute fa fa-arrow-left" title="Show sidebar" t-on-click="callMainView.onClickShowSidebar"/>
|
||||
</t>
|
||||
<t t-if="callMainView.showOverlay or !callMainView.isControllerFloating">
|
||||
<div class="o_CallMainView_controls d-flex justify-content-center w-100 pb-1" t-att-class="{ 'o-isFloating position-absolute bottom-0 pb-3': callMainView.isControllerFloating }">
|
||||
<div class="o_CallMainView_controlsOverlayContainer" t-on-mousemove="callMainView.onMouseMoveOverlay">
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<t t-name="mail.CallSidebarView" owl="1">
|
||||
<t t-if="callSidebarView">
|
||||
<div class="o_CallSidebarView d-flex align-items-center h-100 flex-column">
|
||||
<t t-foreach="callSidebarView.callView.tileParticipantCards" t-as="participantCard" t-key="participantCard.localId">
|
||||
<t t-foreach="callSidebarView.sidebarTiles" t-as="tile" t-key="tile.localId">
|
||||
<CallParticipantCard
|
||||
className="'o_CallSidebarView_participantCard w-100'"
|
||||
record="participantCard"
|
||||
record="tile.participantCard"
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { attr, one } from '@mail/model/model_field';
|
||||
import { clear, insertAndReplace } from '@mail/model/model_field_command';
|
||||
import { attr, many, one } from '@mail/model/model_field';
|
||||
import { clear, insertAndReplace, replace } from '@mail/model/model_field_command';
|
||||
|
||||
import { isEventHandled, markEventHandled } from '@mail/utils/utils';
|
||||
|
||||
@@ -63,13 +63,13 @@ registerModel({
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
onClickHideSidebar(ev) {
|
||||
this.callView.update({ hasSidebar: false });
|
||||
this.callView.update({ isSidebarOpen: false });
|
||||
},
|
||||
/**
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
onClickShowSidebar(ev) {
|
||||
this.callView.update({ hasSidebar: true });
|
||||
this.callView.update({ isSidebarOpen: true });
|
||||
},
|
||||
/**
|
||||
* @param {MouseEvent} ev
|
||||
@@ -117,12 +117,29 @@ registerModel({
|
||||
// Private
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeHasSidebarButton() {
|
||||
return Boolean(this.callView.activeRtcSession && this.showOverlay && !this.callView.threadView.compact);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_computeIsControllerFloating() {
|
||||
return Boolean(this.callView.isFullScreen || this.callView.activeRtcSession && !this.callView.threadView.compact);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeMainTiles() {
|
||||
if (this.callView.activeRtcSession) {
|
||||
return insertAndReplace([{ channelMember: replace(this.callView.activeRtcSession.channelMember) }]);
|
||||
}
|
||||
return insertAndReplace(this.callView.filteredChannelMembers.map(channelMember => ({ channelMember: replace(channelMember) })));
|
||||
},
|
||||
/**
|
||||
* Shows the overlay (buttons) for a set a mount of time.
|
||||
*
|
||||
@@ -154,6 +171,9 @@ registerModel({
|
||||
related: 'callView.channel',
|
||||
required: true,
|
||||
}),
|
||||
hasSidebarButton: attr({
|
||||
compute: '_computeHasSidebarButton',
|
||||
}),
|
||||
/**
|
||||
* Determines if the controller is an overlay or a bottom bar.
|
||||
*/
|
||||
@@ -161,6 +181,11 @@ registerModel({
|
||||
default: false,
|
||||
compute: '_computeIsControllerFloating',
|
||||
}),
|
||||
mainTiles: many('CallMainViewTile', {
|
||||
compute: '_computeMainTiles',
|
||||
inverse: 'callMainViewOwner',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* Determines if we show the overlay with the control buttons.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { insertAndReplace } from '@mail/model/model_field_command';
|
||||
import { one } from '@mail/model/model_field';
|
||||
|
||||
registerModel({
|
||||
name: 'CallMainViewTile',
|
||||
identifyingFields: ['callMainViewOwner', 'channelMember'],
|
||||
fields: {
|
||||
callMainViewOwner: one('CallMainView', {
|
||||
inverse: 'mainTiles',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
channelMember: one('ChannelMember', {
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
participantCard: one('CallParticipantCard', {
|
||||
default: insertAndReplace(),
|
||||
inverse: 'mainViewTileOwner',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
registerModel({
|
||||
name: 'CallParticipantCard',
|
||||
identifyingFields: ['channelMember', ['callViewAsMainCard', 'callViewAsTile']],
|
||||
identifyingFields: [['sidebarViewTileOwner', 'mainViewTileOwner']],
|
||||
recordMethods: {
|
||||
/**
|
||||
* @param {Event} ev
|
||||
@@ -25,7 +25,7 @@ registerModel({
|
||||
return;
|
||||
}
|
||||
if (this.rtcSession) {
|
||||
if (this.callView.activeRtcSession === this.rtcSession && this.callViewAsMainCard) {
|
||||
if (this.callView.activeRtcSession === this.rtcSession && this.mainViewTileOwner) {
|
||||
this.callView.update({ activeRtcSession: clear() });
|
||||
} else {
|
||||
this.callView.update({ activeRtcSession: replace(this.rtcSession) });
|
||||
@@ -68,16 +68,24 @@ registerModel({
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {mail.callView}
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeCallView() {
|
||||
const callView = this.callViewAsMainCard || this.callViewAsTile;
|
||||
if (callView) {
|
||||
return replace(callView);
|
||||
} else {
|
||||
return clear();
|
||||
if (this.sidebarViewTileOwner) {
|
||||
return replace(this.sidebarViewTileOwner.callSidebarViewOwner.callView);
|
||||
}
|
||||
return replace(this.mainViewTileOwner.callMainViewOwner.callView);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeChannelMember() {
|
||||
if (this.sidebarViewTileOwner) {
|
||||
return replace(this.sidebarViewTileOwner.channelMember);
|
||||
}
|
||||
return replace(this.mainViewTileOwner.channelMember);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {boolean}
|
||||
@@ -144,9 +152,8 @@ registerModel({
|
||||
},
|
||||
fields: {
|
||||
channelMember: one('ChannelMember', {
|
||||
compute: '_computeChannelMember',
|
||||
inverse: 'callParticipantCards',
|
||||
required: true,
|
||||
readonly: true,
|
||||
}),
|
||||
/**
|
||||
* Determines whether or not we show the connection info.
|
||||
@@ -160,6 +167,10 @@ registerModel({
|
||||
inboundConnectionTypeText: attr({
|
||||
compute: '_computeInboundConnectionTypeText',
|
||||
}),
|
||||
mainViewTileOwner: one('CallMainViewTile', {
|
||||
inverse: 'participantCard',
|
||||
readonly: true,
|
||||
}),
|
||||
/**
|
||||
* Determines if this card has to be displayed in a minimized form.
|
||||
*/
|
||||
@@ -187,24 +198,14 @@ registerModel({
|
||||
compute: '_computeCallView',
|
||||
inverse: 'participantCards',
|
||||
}),
|
||||
/**
|
||||
* The call view for which this card is the main card.
|
||||
*/
|
||||
callViewAsMainCard: one('CallView', {
|
||||
inverse: 'mainParticipantCard',
|
||||
readonly: true,
|
||||
}),
|
||||
/**
|
||||
* The call view for which this card is one of the tiles.
|
||||
*/
|
||||
callViewAsTile: one('CallView', {
|
||||
inverse: 'tileParticipantCards',
|
||||
readonly: true,
|
||||
}),
|
||||
rtcSession: one('RtcSession', {
|
||||
related: 'channelMember.rtcSession',
|
||||
inverse: 'callParticipantCards',
|
||||
}),
|
||||
sidebarViewTileOwner: one('CallSidebarViewTile', {
|
||||
inverse: 'participantCard',
|
||||
readonly: true,
|
||||
}),
|
||||
callParticipantVideoView: one('CallParticipantVideoView', {
|
||||
compute: '_computeCallParticipantVideoView',
|
||||
inverse: 'callParticipantCardOwner',
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { one } from '@mail/model/model_field';
|
||||
import { many, one } from '@mail/model/model_field';
|
||||
import { insertAndReplace, replace } from '@mail/model/model_field_command';
|
||||
|
||||
registerModel({
|
||||
name: 'CallSidebarView',
|
||||
identifyingFields: ['callView'],
|
||||
recordMethods: {
|
||||
/**
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeSidebarTiles() {
|
||||
return insertAndReplace(this.callView.filteredChannelMembers.map(channelMember => ({ channelMember: replace(channelMember) })));
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
callView: one('CallView', {
|
||||
inverse: 'callSidebarView',
|
||||
required: true,
|
||||
readonly: true,
|
||||
})
|
||||
required: true,
|
||||
}),
|
||||
sidebarTiles: many('CallSidebarViewTile', {
|
||||
compute: '_computeSidebarTiles',
|
||||
inverse: 'callSidebarViewOwner',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { insertAndReplace } from '@mail/model/model_field_command';
|
||||
import { one } from '@mail/model/model_field';
|
||||
|
||||
registerModel({
|
||||
name: 'CallSidebarViewTile',
|
||||
identifyingFields: ['callSidebarViewOwner', 'channelMember'],
|
||||
fields: {
|
||||
callSidebarViewOwner: one('CallSidebarView', {
|
||||
inverse: 'sidebarTiles',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
channelMember: one('ChannelMember', {
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
participantCard: one('CallParticipantCard', {
|
||||
default: insertAndReplace(),
|
||||
inverse: 'sidebarViewTileOwner',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -5,7 +5,7 @@ import { browser } from "@web/core/browser/browser";
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { attr, many, one } from '@mail/model/model_field';
|
||||
import { OnChange } from '@mail/model/model_onchange';
|
||||
import { clear, insert, insertAndReplace, replace } from '@mail/model/model_field_command';
|
||||
import { clear, insertAndReplace, replace } from '@mail/model/model_field_command';
|
||||
|
||||
registerModel({
|
||||
name: 'CallView',
|
||||
@@ -80,11 +80,21 @@ registerModel({
|
||||
* @private
|
||||
*/
|
||||
_computeCallSideBarView() {
|
||||
if (this.mainParticipantCard && this.hasSidebar && !this.threadView.compact) {
|
||||
if (this.activeRtcSession && this.isSidebarOpen && !this.threadView.compact) {
|
||||
return insertAndReplace();
|
||||
}
|
||||
return clear();
|
||||
},
|
||||
_computeFilteredChannelMembers() {
|
||||
const channelMembers = [];
|
||||
for (const channelMember of this.channel.channel.callParticipants) {
|
||||
if (this.filterVideoGrid && !channelMember.isStreaming) {
|
||||
continue;
|
||||
}
|
||||
channelMembers.push(channelMember);
|
||||
}
|
||||
return replace(channelMembers);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -95,7 +105,7 @@ registerModel({
|
||||
if (this.isFullScreen || this.threadView.compact) {
|
||||
return false;
|
||||
}
|
||||
if (this.mainParticipantCard) {
|
||||
if (this.activeRtcSession) {
|
||||
return false;
|
||||
}
|
||||
return !this.channel.rtc || this.channel.videoCount === 0;
|
||||
@@ -107,17 +117,6 @@ registerModel({
|
||||
_computeLayoutSettingsTitle() {
|
||||
return this.env._t("Change Layout");
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_computeMainParticipantCard() {
|
||||
if (!this.messaging || !this.activeRtcSession || !this.threadView || !this.activeRtcSession) {
|
||||
return clear();
|
||||
}
|
||||
return insert({
|
||||
channelMember: replace(this.activeRtcSession.channelMember),
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {string}
|
||||
@@ -125,28 +124,6 @@ registerModel({
|
||||
_computeSettingsTitle() {
|
||||
return this.env._t("Settings");
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeTileParticipantCards() {
|
||||
if (!this.threadView) {
|
||||
return clear();
|
||||
}
|
||||
if (this.activeRtcSession && !this.hasSidebar) {
|
||||
return clear();
|
||||
}
|
||||
const tileCards = [];
|
||||
for (const channelMember of this.channel.channel.callParticipants) {
|
||||
if (this.filterVideoGrid && !channelMember.isStreaming) {
|
||||
continue;
|
||||
}
|
||||
tileCards.push({
|
||||
channelMember: replace(channelMember),
|
||||
});
|
||||
}
|
||||
return insertAndReplace(tileCards);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -202,18 +179,15 @@ registerModel({
|
||||
related: 'threadView.thread',
|
||||
required: true,
|
||||
}),
|
||||
filteredChannelMembers: many('ChannelMember', {
|
||||
compute: '_computeFilteredChannelMembers',
|
||||
}),
|
||||
/**
|
||||
* Determines whether we only display the videos or all the participants
|
||||
*/
|
||||
filterVideoGrid: attr({
|
||||
default: false,
|
||||
}),
|
||||
/**
|
||||
* Determines if the viewer should have a sidebar.
|
||||
*/
|
||||
hasSidebar: attr({
|
||||
default: true,
|
||||
}),
|
||||
/**
|
||||
* Determines if the viewer should be displayed fullScreen.
|
||||
*/
|
||||
@@ -228,20 +202,15 @@ registerModel({
|
||||
default: false,
|
||||
compute: '_computeIsMinimized',
|
||||
}),
|
||||
isSidebarOpen: attr({
|
||||
default: true,
|
||||
}),
|
||||
/**
|
||||
* Text content that is displayed on title of the layout settings dialog.
|
||||
*/
|
||||
layoutSettingsTitle: attr({
|
||||
compute: '_computeLayoutSettingsTitle',
|
||||
}),
|
||||
/**
|
||||
* If set, the card to be displayed as the main card.
|
||||
*/
|
||||
mainParticipantCard: one('CallParticipantCard', {
|
||||
compute: '_computeMainParticipantCard',
|
||||
inverse: 'callViewAsMainCard',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* All the participant cards of the call viewer (main card and tile cards).
|
||||
* this is a technical inverse to distinguish from the other relation 'tileParticipantCards'.
|
||||
@@ -264,14 +233,6 @@ registerModel({
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
/**
|
||||
* List of all participant cards (can either be invitations or rtcSessions).
|
||||
*/
|
||||
tileParticipantCards: many('CallParticipantCard', {
|
||||
compute: '_computeTileParticipantCards',
|
||||
inverse: 'callViewAsTile',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
onChanges: [
|
||||
new OnChange({
|
||||
|
||||
Reference in New Issue
Block a user