[FIX] mail: add more menu for rtc buttons

This commit revert the changes from this PR https://github.com/odoo/odoo/pull/127377

Before this commit:

Chat window shows all 7 rtc buttons due to this the alignment of the button
is not set because there are way too many buttons.

After this commit:

This commit fixes the issue by showing only 5 buttons Mute,Deafen,Video,More,
Close call and other 3 buttons will moved in expandable More menu.

The testcases were changed accordingly.

Task-3346085

closes odoo/odoo#129360

X-original-commit: 909fb073eada42ff22c4ef4b20b44dc5536b250e
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
thsh-odoo
2023-07-24 21:27:32 +02:00
committed by Alexandre Kühn
parent a48fa4fe40
commit 80af1c3d65
4 changed files with 76 additions and 62 deletions
@@ -25,7 +25,7 @@
<i t-else="" class="o-discuss-Call-sidebarToggler p-2 fs-5 cursor-pointer position-absolute oi oi-arrow-left" title="Show sidebar" t-on-click="() => this.state.sidebar = true"/>
</t>
<div t-if="state.overlay or !isControllerFloating" class="o-discuss-Call-overlay d-flex justify-content-center w-100 pb-1" t-att-class="{ 'o-isFloating position-absolute bottom-0 pb-3': isControllerFloating }">
<div t-att-class="{ 'w-100': props.compact }" t-on-mousemove="onMousemoveOverlay">
<div t-on-mousemove="onMousemoveOverlay">
<CallActionList thread="props.thread" compact="props.compact" fullscreen="{ isActive: state.isFullscreen, enter: () => this.enterFullScreen(), exit: () => this.exitFullScreen() }"/>
</div>
</div>
@@ -5,8 +5,12 @@ import { useRtc } from "@mail/discuss/call/common/rtc_hook";
import { Component } from "@odoo/owl";
import { isMobileOS } from "@web/core/browser/feature_detection";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { _t } from "@web/core/l10n/translation";
export class CallActionList extends Component {
static components = { Dropdown, DropdownItem };
static props = ["thread", "fullscreen", "compact?"];
static template = "discuss.CallActionList";
@@ -14,6 +18,44 @@ export class CallActionList extends Component {
this.rtc = useRtc();
}
get MORE() {
return _t("More");
}
get moreActions() {
const acts = [];
acts.push({
id: "raiseHand",
name: !this.rtc.state?.selfSession.raisingHand ? _t("Raise Hand") : _t("Lower Hand"),
icon: "fa fa-fw fa-hand-paper-o",
onSelect: (ev) => this.onClickRaiseHand(ev),
});
if (isMobileOS) {
acts.push({
id: "shareScreen",
name: !this.rtc.state.sendScreen ? _t("Share Screen") : _t("Stop Sharing Screen"),
icon: "fa fa-fw fa-desktop",
onSelect: () => this.rtc.toggleVideo("screen"),
});
}
if (!this.props.fullscreen.isActive) {
acts.push({
id: "fullScreen",
name: _t("Enter Full Screen"),
icon: "fa fa-fw fa-arrows-alt",
onSelect: () => this.props.fullscreen.enter(),
});
} else {
acts.push({
id: "exitFullScreen",
name: _t("Exit Full Screen"),
icon: "fa fa-fw fa-compress",
onSelect: () => this.props.fullscreen.exit(),
});
}
return acts;
}
get isOfActiveCall() {
return Boolean(this.props.thread.id === this.rtc.state?.channel?.id);
}
@@ -7,8 +7,8 @@
<t t-if="isOfActiveCall and rtc.state.selfSession">
<t t-if="rtc.state?.selfSession.isMute" t-set="micText">Unmute</t>
<t t-else="" t-set="micText">Mute</t>
<button class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall }"
<button class="btn d-flex m-1 border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{ 'p-2': isSmall, 'p-3': !isSmall }"
t-att-aria-label="micText"
t-att-title="micText"
t-on-click="onClickMicrophone">
@@ -23,8 +23,8 @@
</button>
<t t-if="rtc.state?.selfSession.isDeaf" t-set="headphoneText">Undeafen</t>
<t t-else="" t-set="headphoneText">Deafen</t>
<button class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall }"
<button class="btn d-flex m-1 border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{ 'p-2': isSmall, 'p-3': !isSmall }"
t-att-aria-label="headphoneText"
t-att-title="headphoneText"
t-on-click="onClickDeafen">
@@ -37,23 +37,12 @@
}"/>
</div>
</button>
<t t-if="rtc.state?.selfSession.raisingHand" t-set="handText">Lower hand</t>
<t t-else="" t-set="handText">Raise hand</t>
<button class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall, 'bg-500' : rtc.state?.selfSession.raisingHand }"
t-att-aria-label="handText"
t-att-title="handText"
t-on-click="onClickRaiseHand">
<div class="fa-stack">
<i class="fa fa-stack-1x fa-hand-paper-o" t-att-class="{'fa-lg': !isSmall }"/>
</div>
</button>
<t t-if="rtc.state.sendCamera" t-set="cameraText">Stop camera</t>
<t t-else="" t-set="cameraText">Turn camera on</t>
<button class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
<button class="btn d-flex m-1 border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{
'p-2': isSmall,
'p-3 m-1': !isSmall,
'p-3': !isSmall,
}"
t-att-aria-label="cameraText"
t-att-title="cameraText"
@@ -62,43 +51,22 @@
<i class="fa fa-video-camera fa-stack-1x" t-att-class="{ 'fa-lg': !isSmall, 'text-success': rtc.state.sendCamera }"/>
</div>
</button>
<t t-if="rtc.state.sendScreen" t-set="screenSharingText">Stop screen sharing</t>
<t t-else="" t-set="screenSharingText">Share screen</t>
<button t-if="!isMobileOS" class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
t-att-class="{
'p-2': isSmall,
'p-3 m-1': !isSmall,
}"
t-att-aria-label="screenSharingText"
t-att-title="screenSharingText"
t-on-click="() => this.rtc.toggleVideo('screen')">
<div class="fa-stack">
<i class="fa fa-desktop fa-stack-1x" t-att-class="{ 'fa-lg': !isSmall, 'text-success': rtc.state.sendScreen }"/>
</div>
</button>
<button t-if="!props.fullscreen.isActive" class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
aria-label="Enter Full Screen"
title="Enter Full Screen"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall }"
t-on-click="props.fullscreen.enter"
>
<div class="fa-stack">
<i class="fa fa-arrows-alt fa-stack-1x" t-att-class="{ 'fa-lg': !isSmall }"/>
</div>
</button>
<button t-if="props.fullscreen.isActive" class="btn d-flex border-0 rounded-circle shadow-none opacity-100 opacity-75-hover"
aria-label="Exit Full Screen"
title="Exit Full Screen"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall }"
t-on-click="props.fullscreen.exit"
>
<div class="fa-stack">
<i class="fa fa-compress fa-stack-1x" t-att-class="{ 'fa-lg': !isSmall }"/>
</div>
</button>
<Dropdown position="'top-end'" togglerClass="`btn d-flex m-1 border-0 rounded-circle shadow-none opacity-100 opacity-75-hover ${ isSmall ? 'p-2' : 'p-3' }`" menuClass="'d-flex flex-column py-0'" title="MORE">
<t t-set-slot="toggler">
<div class="fa-stack">
<i class="fa fa-ellipsis-v fa-stack-1x" t-att-class="{ 'fa-lg': !isSmall }"/>
</div>
</t>
<t t-set-slot="default">
<DropdownItem t-foreach="moreActions" t-as="action" t-key="action.id" class="'btn rounded-0 d-flex align-items-center px-2 py-2 m-0 opacity-75 opacity-100-hover'" title="action.name" onSelected="action.onSelect">
<i t-att-class="action.icon"/>
<span class="mx-2" t-out="action.name"/>
</DropdownItem>
</t>
</Dropdown>
</t>
<button t-if="props.thread.rtcInvitingSession and !isOfActiveCall" class="btn btn-danger d-flex border-0 rounded-circle shadow-none"
t-att-class="{ 'p-2': isSmall, 'p-3 m-1': !isSmall }"
<button t-if="props.thread.rtcInvitingSession and !isOfActiveCall" class="btn btn-danger d-flex m-1 border-0 rounded-circle shadow-none"
t-att-class="{ 'p-2': isSmall, 'p-3': !isSmall }"
aria-label="Reject"
title="Reject"
t-att-disabled="rtc.state.hasPendingRequest"
@@ -109,9 +77,9 @@
</button>
<t t-if="props.thread === rtc.state.channel" t-set="callText">Disconnect</t>
<t t-else="" t-set="callText">Join Call</t>
<button class="btn d-flex border-0 rounded-circle shadow-none"
<button class="btn d-flex m-1 border-0 rounded-circle shadow-none"
t-att-aria-label="callText"
t-att-class="{ 'btn-danger': isOfActiveCall, 'p-2': isSmall, 'p-3 m-1': !isSmall, 'btn-success': !isOfActiveCall }"
t-att-class="{ 'btn-danger': isOfActiveCall, 'p-2': isSmall, 'p-3': !isSmall, 'btn-success': !isOfActiveCall }"
t-att-disabled="rtc.state.hasPendingRequest"
t-att-title="callText"
t-on-click="onClickToggleAudioCall">
@@ -28,14 +28,16 @@ QUnit.test("basic rendering", async (assert) => {
assert.containsOnce($, ".o-discuss-CallParticipantCard[aria-label='Mitchell Admin']");
assert.containsOnce($, ".o-discuss-CallActionList");
assert.containsOnce($, ".o-discuss-CallMenu-buttonContent");
assert.containsN($, ".o-discuss-CallActionList button", 7);
assert.containsN($, ".o-discuss-CallActionList button", 5);
assert.containsOnce($, "button[aria-label='Unmute'], button[aria-label='Mute']"); // FIXME depends on current browser permission
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Deafen']");
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Raise hand']");
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Turn camera on']");
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Share screen']");
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Enter Full Screen']");
assert.containsOnce($, "button[title='More']");
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Disconnect']");
await click("button[title='More']");
assert.containsOnce($, "[title='Raise Hand']");
assert.containsOnce($, "[title='Share Screen']");
assert.containsOnce($, "[title='Enter Full Screen']");
});
QUnit.test("no call with odoobot", async (assert) => {
@@ -177,9 +179,11 @@ QUnit.test("can share screen", async (assert) => {
const { openDiscuss } = await start();
await openDiscuss(channelId);
await click(".o-mail-Discuss-header button[title='Start a Call']");
await click(".o-discuss-CallActionList button[title='Share screen']");
await click(".o-discuss-CallActionList [title='More']");
await click("[title='Share Screen']");
assert.containsOnce($, ".o-discuss-CallParticipantCard video");
await click(".o-discuss-CallActionList button[title='Stop screen sharing']");
await click(".o-discuss-CallActionList [title='More']");
await click("[title='Stop Sharing Screen']");
assert.containsNone($, ".o-discuss-CallParticipantCard video");
});