mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-10 23:25:52 +00:00
Drop observable-hooks in favor of useBehavior
With this change, views now read every reactive value through `useBehavior`, as `architecture.md` already prescribes. Where a view reads a plain stream, the view model now exposes a `Behavior`.
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
mockRemoteScreenShare,
|
||||
} from "../../utils/test";
|
||||
import { constant } from "../Behavior";
|
||||
import { showConnectionStats } from "../../settings/settings";
|
||||
|
||||
global.MediaStreamTrack = class {} as unknown as {
|
||||
new (): MediaStreamTrack;
|
||||
@@ -42,6 +43,12 @@ vi.mock("../../Platform", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const observeRtpStreamStatsMock = vi.hoisted(() => vi.fn());
|
||||
vi.mock("./observeRtpStreamStats", async (importOriginal) => ({
|
||||
...(await importOriginal<Record<string, unknown>>()),
|
||||
observeRtpStreamStats$: observeRtpStreamStatsMock,
|
||||
}));
|
||||
|
||||
const rtcMembership = mockRtcMembership("@alice:example.org", "AAAA");
|
||||
|
||||
test("control a participant's volume", () => {
|
||||
@@ -289,3 +296,37 @@ test("remote media is not in waiting state when user does not intend to publish
|
||||
);
|
||||
expect(vm.waitingForMedia$.value).toBe(false);
|
||||
});
|
||||
|
||||
test("user media polls stream stats only while the setting is on", () => {
|
||||
const participant = mockRemoteParticipant({});
|
||||
const vm = mockRemoteMedia(rtcMembership, {}, participant);
|
||||
onTestFinished(() => showConnectionStats.setValue(false));
|
||||
withTestScheduler(({ cold, expectObservable, schedule }) => {
|
||||
const stats = { type: "inbound-rtp" } as RTCInboundRtpStreamStats;
|
||||
observeRtpStreamStatsMock.mockImplementation(() =>
|
||||
cold("-s", { s: stats }),
|
||||
);
|
||||
schedule("-a-b", {
|
||||
a() {
|
||||
showConnectionStats.setValue(true);
|
||||
},
|
||||
b() {
|
||||
showConnectionStats.setValue(false);
|
||||
},
|
||||
});
|
||||
expectObservable(vm.audioStreamStats$).toBe("u-su", {
|
||||
u: undefined,
|
||||
s: stats,
|
||||
});
|
||||
});
|
||||
expect(observeRtpStreamStatsMock).toHaveBeenCalledWith(
|
||||
participant,
|
||||
Track.Source.Microphone,
|
||||
"inbound-rtp",
|
||||
);
|
||||
expect(observeRtpStreamStatsMock).toHaveBeenCalledWith(
|
||||
participant,
|
||||
Track.Source.Camera,
|
||||
"inbound-rtp",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
BehaviorSubject,
|
||||
combineLatest,
|
||||
map,
|
||||
type Observable,
|
||||
of,
|
||||
Subject,
|
||||
switchMap,
|
||||
@@ -54,10 +53,10 @@ export interface BaseUserMediaViewModel extends BaseMemberMediaViewModel {
|
||||
rtcBackendIdentity: string;
|
||||
handRaised$: Behavior<Date | null>;
|
||||
reaction$: Behavior<ReactionOption | null>;
|
||||
audioStreamStats$: Observable<
|
||||
audioStreamStats$: Behavior<
|
||||
RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined
|
||||
>;
|
||||
videoStreamStats$: Observable<
|
||||
videoStreamStats$: Behavior<
|
||||
RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined
|
||||
>;
|
||||
/**
|
||||
@@ -94,6 +93,21 @@ export function createBaseUserMedia(
|
||||
);
|
||||
const toggleCropVideo$ = new Subject<void>();
|
||||
const videoAspectRatio$ = new BehaviorSubject(NaN);
|
||||
const streamStats$ = (
|
||||
scope: ObservableScope,
|
||||
source: Track.Source,
|
||||
): Behavior<
|
||||
RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined
|
||||
> =>
|
||||
scope.behavior(
|
||||
combineLatest([participant$, showConnectionStats.value$]).pipe(
|
||||
switchMap(([p, showConnectionStats]) =>
|
||||
!p || !showConnectionStats
|
||||
? of(undefined)
|
||||
: observeRtpStreamStats$(p, source, statsType),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
...createMemberMedia(scope, {
|
||||
@@ -130,25 +144,8 @@ export function createBaseUserMedia(
|
||||
rtcBackendIdentity,
|
||||
handRaised$,
|
||||
reaction$,
|
||||
audioStreamStats$: combineLatest([
|
||||
participant$,
|
||||
showConnectionStats.value$,
|
||||
]).pipe(
|
||||
switchMap(([p, showConnectionStats]) => {
|
||||
//
|
||||
if (!p || !showConnectionStats) return of(undefined);
|
||||
return observeRtpStreamStats$(p, Track.Source.Microphone, statsType);
|
||||
}),
|
||||
),
|
||||
videoStreamStats$: combineLatest([
|
||||
participant$,
|
||||
showConnectionStats.value$,
|
||||
]).pipe(
|
||||
switchMap(([p, showConnectionStats]) => {
|
||||
if (!p || !showConnectionStats) return of(undefined);
|
||||
return observeRtpStreamStats$(p, Track.Source.Camera, statsType);
|
||||
}),
|
||||
),
|
||||
audioStreamStats$: streamStats$(scope, Track.Source.Microphone),
|
||||
videoStreamStats$: streamStats$(scope, Track.Source.Camera),
|
||||
setVideoAspectRatio: (ratio) => videoAspectRatio$.next(ratio),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user