Use call view model for hand raised reactions

This commit is contained in:
Half-Shot
2024-12-09 15:19:27 +00:00
parent 081221731e
commit 73ee088605
2 changed files with 29 additions and 17 deletions

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { ReactNode, useDeferredValue, useEffect, useMemo } from "react";
import { filter, interval, throttle } from "rxjs";
import { filter, interval, map, scan, throttle } from "rxjs";
import { CallViewModel } from "../state/CallViewModel";
import joinCallSoundMp3 from "../sound/join_call.mp3";
@@ -51,19 +51,6 @@ export function CallEventAudioRenderer({
});
const audioEngineRef = useLatest(audioEngineCtx);
const { raisedHands } = useReactions();
const raisedHandCount = useMemo(
() => Object.keys(raisedHands).length,
[raisedHands],
);
const previousRaisedHandCount = useDeferredValue(raisedHandCount);
useEffect(() => {
if (audioEngineRef.current && previousRaisedHandCount < raisedHandCount) {
audioEngineRef.current.playSound("raiseHand");
}
}, [audioEngineRef, previousRaisedHandCount, raisedHandCount]);
useEffect(() => {
const joinSub = vm.memberChanges
.pipe(
@@ -89,9 +76,14 @@ export function CallEventAudioRenderer({
audioEngineRef.current?.playSound("left");
});
const handRaisedSub = vm.handRaised.subscribe(() => {
audioEngineRef.current?.playSound("raiseHand");
});
return (): void => {
joinSub.unsubscribe();
leftSub.unsubscribe();
handRaisedSub.unsubscribe();
};
}, [audioEngineRef, vm]);

View File

@@ -26,7 +26,6 @@ import {
Subject,
combineLatest,
concat,
distinct,
distinctUntilChanged,
filter,
forkJoin,
@@ -1099,13 +1098,16 @@ export class CallViewModel extends ViewModel {
);
public readonly handsRaised = new Subject<Record<string, Date>>();
public readonly reactions = new Subject<Record<string, ReactionOption>>();
private readonly reactions = new Subject<Record<string, ReactionOption>>();
public updateReactions(data: ReturnType<typeof useReactions>) {
this.handsRaised.next(data.raisedHands);
this.reactions.next(data.reactions);
}
/**
* Emits an array of reactions that should be visible on the screen.
*/
public readonly visibleReactions = showReactions.value
.pipe(switchMap((show) => (show ? this.reactions : of({}))))
.pipe(
@@ -1125,6 +1127,9 @@ export class CallViewModel extends ViewModel {
)
.pipe(this.scope.state());
/**
* Emits an array of reactions that should be played.
*/
public readonly audibleReactions = playReactionsSound.value
.pipe(
switchMap((show) =>
@@ -1147,10 +1152,25 @@ export class CallViewModel extends ViewModel {
{ playing: [], newSounds: [] },
),
map((v) => v.newSounds),
distinct(),
)
.pipe(this.scope.state());
/**
* Emits an event every time a new hand is raised in
* the call.
*/
public readonly handRaised = this.handsRaised.pipe(
map((v) => Object.keys(v).length),
scan(
(acc, newValue) => ({
value: newValue,
playSounds: newValue > acc.value,
}),
{ value: 0, playSounds: false },
),
filter((v) => v.playSounds),
);
public constructor(
// A call is permanently tied to a single Matrix room and LiveKit room
private readonly matrixRTCSession: MatrixRTCSession,