[FIX] mail: only play rtc sounds on main tab
Before this commit, rtc join/leave sounds were played on every tab. This can be due to two issues: - notifications related to the current user should not play sound since it is already played by the tab that triggered the action. - only the main tab should play the sound. This commit implements this behavior. Steps to reproduce the issue: - Open two tabs - Start a call on the general channel - Notice that the "join" sound was played twice - Leave the call - The same applies for the "leave" sound task-3355352 closes odoo/odoo#144436 X-original-commit: dfbd95f Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com> Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -1553,7 +1553,15 @@ export class Rtc {
|
||||
return;
|
||||
}
|
||||
const oldCount = channel.rtcSessions.length;
|
||||
const hadSelfSession = Boolean(this.state.selfSession?.in(channel.rtcSessions));
|
||||
channel.rtcSessions = sessionsData;
|
||||
if (
|
||||
!hadSelfSession ||
|
||||
hadSelfSession !== Boolean(this.state.selfSession?.in(channel.rtcSessions)) ||
|
||||
!this.store.env.services["multi_tab"].isOnMainTab()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (channel.rtcSessions.length > oldCount) {
|
||||
this.soundEffectsService.play("channel-join");
|
||||
} else if (channel.rtcSessions.length < oldCount) {
|
||||
|
||||
@@ -105,16 +105,6 @@ QUnit.test("should disconnect when closing page while in call", async (assert) =
|
||||
});
|
||||
|
||||
QUnit.test("should display invitations", async (assert) => {
|
||||
patchWithCleanup(browser, {
|
||||
Audio: class extends Audio {
|
||||
pause() {
|
||||
assert.step("pause_sound_effect");
|
||||
}
|
||||
play() {
|
||||
assert.step("play_sound_effect");
|
||||
}
|
||||
},
|
||||
});
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "InvitationSender" });
|
||||
@@ -126,7 +116,17 @@ QUnit.test("should display invitations", async (assert) => {
|
||||
channel_member_id: memberId,
|
||||
channel_id: channelId,
|
||||
});
|
||||
await start();
|
||||
const { env } = await start();
|
||||
patchWithCleanup(env.services["mail.sound_effects"], {
|
||||
play(name) {
|
||||
assert.step(`play - ${name}`);
|
||||
super.play(...arguments);
|
||||
},
|
||||
stop(name) {
|
||||
assert.step(`stop - ${name}`);
|
||||
super.stop(...arguments);
|
||||
},
|
||||
});
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
id: channelId,
|
||||
@@ -135,7 +135,7 @@ QUnit.test("should display invitations", async (assert) => {
|
||||
},
|
||||
});
|
||||
await contains(".o-discuss-CallInvitation");
|
||||
assert.verifySteps(["play_sound_effect"]);
|
||||
assert.verifySteps(["play - incoming-call"]);
|
||||
// Simulate stop receiving call invitation
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
@@ -145,7 +145,7 @@ QUnit.test("should display invitations", async (assert) => {
|
||||
},
|
||||
});
|
||||
await contains(".o-discuss-CallInvitation", { count: 0 });
|
||||
assert.verifySteps(["pause_sound_effect"]);
|
||||
assert.verifySteps(["stop - incoming-call"]);
|
||||
});
|
||||
|
||||
QUnit.test("can share screen", async () => {
|
||||
@@ -223,3 +223,31 @@ QUnit.test("Click on inset card should replace the inset and active stream toget
|
||||
await contains("video[type='screen'].o-inset");
|
||||
await contains("video[type='camera']:not(.o-inset)");
|
||||
});
|
||||
|
||||
QUnit.test("join/leave sounds are only played on main tab", async (assert) => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
patchWithCleanup(tab1.env.services["mail.sound_effects"], {
|
||||
play(name) {
|
||||
assert.step(`tab1 - play - ${name}`);
|
||||
},
|
||||
});
|
||||
patchWithCleanup(tab2.env.services["mail.sound_effects"], {
|
||||
play(name) {
|
||||
assert.step(`tab2 - play - ${name}`);
|
||||
},
|
||||
});
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
await click("[title='Start a Call']", { target: tab1.target });
|
||||
await contains(".o-discuss-Call", { target: tab1.target });
|
||||
await contains(".o-discuss-Call", { target: tab2.target });
|
||||
assert.verifySteps(["tab1 - play - channel-join"]);
|
||||
await click("[title='Disconnect']:not([disabled])", { target: tab1.target });
|
||||
await contains(".o-discuss-Call", { target: tab1.target, count: 0 });
|
||||
await contains(".o-discuss-Call", { target: tab2.target, count: 0 });
|
||||
assert.verifySteps(["tab1 - play - channel-leave"]);
|
||||
});
|
||||
|
||||
@@ -167,7 +167,7 @@ patch(MockServer.prototype, {
|
||||
return this._mockRouteMailRtcChannelLeaveCall(args.channel_id);
|
||||
}
|
||||
if (route === "/mail/rtc/session/update_and_broadcast") {
|
||||
return;
|
||||
return this._mockRouteMailRtcSessionUpdateAndBroadcast(args.session_id, args.values);
|
||||
}
|
||||
if (route === "/mail/starred/messages") {
|
||||
const { search_term, after, before, limit } = args;
|
||||
@@ -602,6 +602,23 @@ patch(MockServer.prototype, {
|
||||
}
|
||||
this.pyEnv["bus.bus"]._sendmany(notifications);
|
||||
},
|
||||
/**
|
||||
* Simulates the `/mail/rtc/session/update_and_broadcast` route.
|
||||
*
|
||||
* @param {number} session_id
|
||||
* @param {object} values
|
||||
*/
|
||||
async _mockRouteMailRtcSessionUpdateAndBroadcast(session_id, values) {
|
||||
const [session] = this.pyEnv["discuss.channel.rtc.session"].searchRead([
|
||||
["id", "=", session_id],
|
||||
]);
|
||||
const [currentChannelMember] = this.pyEnv["discuss.channel.member"].searchRead([
|
||||
["id", "=", session.channel_member_id[0]],
|
||||
]);
|
||||
if (session && currentChannelMember.partner_id[0] === this.pyEnv.currentPartnerId) {
|
||||
this._mockDiscussChannelRtcSession__updateAndBroadcast(session.id, values);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Simulates the `/mail/thread/data` route.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,30 @@ import { patch } from "@web/core/utils/patch";
|
||||
import { MockServer } from "@web/../tests/helpers/mock_server";
|
||||
|
||||
patch(MockServer.prototype, {
|
||||
mockCreate(model) {
|
||||
if (model !== "discuss.channel.rtc.session") {
|
||||
return super.mockCreate(...arguments);
|
||||
}
|
||||
const sessionIds = super.mockCreate(...arguments);
|
||||
const channelInfo =
|
||||
this._mockDiscussChannelRtcSession_DiscussChannelRtcSessionFormatByChannel(sessionIds);
|
||||
const notifications = [];
|
||||
for (const [channelId, sessionData] of Object.entries(channelInfo)) {
|
||||
const [channel] = this.pyEnv["discuss.channel"].searchRead([
|
||||
["id", "=", Number(channelId)],
|
||||
]);
|
||||
notifications.push([
|
||||
channel,
|
||||
"discuss.channel/rtc_sessions_update",
|
||||
{
|
||||
id: channel.id,
|
||||
rtcSessions: [["ADD", sessionData]],
|
||||
},
|
||||
]);
|
||||
}
|
||||
this.pyEnv["bus.bus"]._sendmany(notifications);
|
||||
return sessionIds;
|
||||
},
|
||||
/**
|
||||
* Simulates `_mail_rtc_session_format` on `discuss.channel.rtc.session`.
|
||||
*
|
||||
@@ -54,4 +78,21 @@ patch(MockServer.prototype, {
|
||||
}
|
||||
return data;
|
||||
},
|
||||
/**
|
||||
* Simulates `_update_and_broadcast` on `discuss.channel.rtc.session`.
|
||||
*
|
||||
* @param {object} values
|
||||
*/
|
||||
_mockDiscussChannelRtcSession__updateAndBroadcast(id, values) {
|
||||
this.pyEnv["discuss.channel.rtc.session"].write([id], values);
|
||||
const sessionData = this._mockDiscussChannelRtcSession_DiscussChannelRtcSessionFormat(id);
|
||||
const [channel] = this.pyEnv["discuss.channel"].searchRead([
|
||||
["id", "=", sessionData.channelMember.thread.id],
|
||||
]);
|
||||
this.pyEnv["bus.bus"]._sendone(
|
||||
channel,
|
||||
"discuss.channel.rtc.session/update_and_broadcast",
|
||||
{ data: sessionData, channelId: channel.id }
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user