mirror of
https://github.com/vector-im/element-call.git
synced 2026-03-31 07:00:26 +00:00
Integrate raise hand sound into call event renderer.
This commit is contained in:
@@ -51,7 +51,14 @@ afterEach(() => {
|
||||
window.HTMLMediaElement.prototype.play = originalPlayFn;
|
||||
});
|
||||
|
||||
test("plays a sound when entering a call", () => {
|
||||
/**
|
||||
* We don't want to play a sound when loading the call state
|
||||
* because typically this occurs in two stages. We first join
|
||||
* the call as a local participant and *then* the remote
|
||||
* participants join from our perspective. We don't want to make
|
||||
* a noise every time.
|
||||
*/
|
||||
test("does NOT play a sound when entering a call", () => {
|
||||
const audioIsPlaying: string[] = mockMediaPlay();
|
||||
const members = new Map([alice, bob].map((p) => [p.userId, p]));
|
||||
const remoteParticipants = of([aliceParticipant]);
|
||||
@@ -75,10 +82,7 @@ test("plays a sound when entering a call", () => {
|
||||
);
|
||||
|
||||
render(<CallEventAudioRenderer vm={vm} />);
|
||||
expect(audioIsPlaying).toEqual([
|
||||
// Joining the call
|
||||
enterSound,
|
||||
]);
|
||||
expect(audioIsPlaying).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("plays no sound when muted", () => {
|
||||
@@ -141,8 +145,6 @@ test("plays a sound when a user joins", () => {
|
||||
});
|
||||
// Play a sound when joining a call.
|
||||
expect(audioIsPlaying).toEqual([
|
||||
// Joining the call
|
||||
enterSound,
|
||||
// Bob leaves
|
||||
enterSound,
|
||||
]);
|
||||
@@ -178,14 +180,12 @@ test("plays a sound when a user leaves", () => {
|
||||
liveKitRoom.removeParticipant(aliceParticipant);
|
||||
});
|
||||
expect(audioIsPlaying).toEqual([
|
||||
// Joining the call
|
||||
enterSound,
|
||||
// Alice leaves
|
||||
leaveSound,
|
||||
]);
|
||||
});
|
||||
|
||||
test("plays no sound when the participant list", () => {
|
||||
test("plays no sound when the participant list is more than the maximum size", () => {
|
||||
const audioIsPlaying: string[] = mockMediaPlay();
|
||||
const members = new Map([alice].map((p) => [p.userId, p]));
|
||||
const remoteParticipants = new Map<string, RemoteParticipant>([
|
||||
|
||||
@@ -5,14 +5,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { ReactNode, useEffect } from "react";
|
||||
import { ReactNode, useDeferredValue, useEffect, useMemo } from "react";
|
||||
import { debounce, filter, interval, throttle } from "rxjs";
|
||||
import { CallViewModel } from "../state/CallViewModel";
|
||||
import joinCallSoundMp3 from "../sound/join_call.mp3";
|
||||
import joinCallSoundOgg from "../sound/join_call.ogg";
|
||||
import leftCallSoundMp3 from "../sound/left_call.mp3";
|
||||
import leftCallSoundOgg from "../sound/left_call.ogg";
|
||||
import handSoundOgg from "../sound/raise_hand.ogg?url";
|
||||
import handSoundMp3 from "../sound/raise_hand.mp3?url";
|
||||
import { prefetchSounds, useAudioContext } from "../useAudioContext";
|
||||
import { useReactions } from "../useReactions";
|
||||
|
||||
// Do not play any sounds if the participant count has exceeded this
|
||||
// number.
|
||||
@@ -29,6 +32,10 @@ const Sounds = prefetchSounds({
|
||||
mp3: leftCallSoundMp3,
|
||||
ogg: leftCallSoundOgg,
|
||||
},
|
||||
raiseHand: {
|
||||
mp3: handSoundMp3,
|
||||
ogg: handSoundOgg,
|
||||
},
|
||||
});
|
||||
|
||||
export function CallEventAudioRenderer({
|
||||
@@ -41,6 +48,19 @@ export function CallEventAudioRenderer({
|
||||
latencyHint: "interactive",
|
||||
});
|
||||
|
||||
const { raisedHands } = useReactions();
|
||||
const raisedHandCount = useMemo(
|
||||
() => Object.keys(raisedHands).length,
|
||||
[raisedHands],
|
||||
);
|
||||
const previousRaisedHandCount = useDeferredValue(raisedHandCount);
|
||||
|
||||
useEffect(() => {
|
||||
if (audioEngineCtx && previousRaisedHandCount < raisedHandCount) {
|
||||
audioEngineCtx.playSound("raiseHand");
|
||||
}
|
||||
}, [audioEngineCtx, previousRaisedHandCount, raisedHandCount]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!audioEngineCtx) {
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
TouchEvent,
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useDeferredValue,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
@@ -81,11 +80,8 @@ import { makeSpotlightLandscapeLayout } from "../grid/SpotlightLandscapeLayout";
|
||||
import { makeSpotlightPortraitLayout } from "../grid/SpotlightPortraitLayout";
|
||||
import { GridTileViewModel, TileViewModel } from "../state/TileViewModel";
|
||||
import { ReactionsProvider, useReactions } from "../useReactions";
|
||||
import handSoundOgg from "../sound/raise_hand.ogg?url";
|
||||
import handSoundMp3 from "../sound/raise_hand.mp3?url";
|
||||
import { ReactionsAudioRenderer } from "./ReactionAudioRenderer";
|
||||
import { useSwitchCamera } from "./useSwitchCamera";
|
||||
import { soundEffectVolumeSetting, useSetting } from "../settings/settings";
|
||||
import { ReactionsOverlay } from "./ReactionsOverlay";
|
||||
import { CallEventAudioRenderer } from "./CallEventAudioRenderer";
|
||||
|
||||
@@ -183,14 +179,7 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
connState,
|
||||
onShareClick,
|
||||
}) => {
|
||||
const [soundEffectVolume] = useSetting(soundEffectVolumeSetting);
|
||||
const { supportsReactions, raisedHands, sendReaction, toggleRaisedHand } =
|
||||
useReactions();
|
||||
const raisedHandCount = useMemo(
|
||||
() => Object.keys(raisedHands).length,
|
||||
[raisedHands],
|
||||
);
|
||||
const previousRaisedHandCount = useDeferredValue(raisedHandCount);
|
||||
const { supportsReactions, sendReaction, toggleRaisedHand } = useReactions();
|
||||
|
||||
useWakeLock();
|
||||
|
||||
@@ -340,25 +329,6 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
[vm],
|
||||
);
|
||||
|
||||
// Play a sound when the raised hand count increases.
|
||||
const handRaisePlayer = useRef<HTMLAudioElement>(null);
|
||||
useEffect(() => {
|
||||
if (!handRaisePlayer.current) {
|
||||
return;
|
||||
}
|
||||
if (previousRaisedHandCount < raisedHandCount) {
|
||||
handRaisePlayer.current.volume = soundEffectVolume;
|
||||
handRaisePlayer.current.play().catch((ex) => {
|
||||
logger.warn("Failed to play raise hand sound", ex);
|
||||
});
|
||||
}
|
||||
}, [
|
||||
raisedHandCount,
|
||||
handRaisePlayer,
|
||||
previousRaisedHandCount,
|
||||
soundEffectVolume,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
widget?.api.transport
|
||||
.send(
|
||||
@@ -672,10 +642,6 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
<RoomAudioRenderer />
|
||||
{renderContent()}
|
||||
<CallEventAudioRenderer vm={vm} />
|
||||
<audio ref={handRaisePlayer} preload="auto" hidden>
|
||||
<source src={handSoundOgg} type="audio/ogg; codecs=vorbis" />
|
||||
<source src={handSoundMp3} type="audio/mpeg" />
|
||||
</audio>
|
||||
<ReactionsAudioRenderer />
|
||||
<ReactionsOverlay />
|
||||
{footer}
|
||||
|
||||
Reference in New Issue
Block a user