From d5d8949fcc93a6541c6b13d7d9f6f9e5b470bbe5 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Wed, 30 Oct 2024 17:19:21 +0100 Subject: [PATCH] WIP --- e2e-tests/ts-client/app/playwright.config.ts | 2 +- e2e-tests/ts-client/app/src/App.tsx | 5 - examples/ts-client/simple-app/src/main.ts | 75 ++++-------- .../src/hooks/useFishjamClientState.ts | 6 +- packages/react-client/src/hooks/usePeers.ts | 14 +-- .../react-client/src/hooks/useScreenShare.ts | 1 - .../react-client/src/hooks/useTrackManager.ts | 1 - packages/react-client/src/types/internal.ts | 8 +- packages/react-client/src/utils/track.ts | 22 ++-- packages/ts-client/src/FishjamClient.ts | 115 +++++++++++------- packages/ts-client/src/index.ts | 2 +- packages/ts-client/src/webrtc/internal.ts | 3 +- .../ts-client/src/webrtc/tracks/Remote.ts | 18 +-- .../ts-client/src/webrtc/webRTCEndpoint.ts | 4 +- .../events/encodingSwitchedEvent.test.ts | 6 +- .../tests/events/trackAddedEvent.test.ts | 2 +- packages/ts-client/tests/mocks.ts | 2 +- 17 files changed, 125 insertions(+), 161 deletions(-) diff --git a/e2e-tests/ts-client/app/playwright.config.ts b/e2e-tests/ts-client/app/playwright.config.ts index 6710ec3f..70533a27 100644 --- a/e2e-tests/ts-client/app/playwright.config.ts +++ b/e2e-tests/ts-client/app/playwright.config.ts @@ -18,7 +18,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: 1, + workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: [ ["list"], diff --git a/e2e-tests/ts-client/app/src/App.tsx b/e2e-tests/ts-client/app/src/App.tsx index 81c62075..292a3dd2 100644 --- a/e2e-tests/ts-client/app/src/App.tsx +++ b/e2e-tests/ts-client/app/src/App.tsx @@ -75,20 +75,15 @@ class RemoteStore { } snapshot() { - console.log("Snapshot"); - const newTracks = webrtc.getRemoteTracks(); const newEndpoints = webrtc.getRemoteEndpoints(); const ids = Object.keys(newTracks).sort().join(":") + Object.keys(newEndpoints).sort().join(":"); if (!(ids in this.cache) || this.invalidateCache) { - console.log({ name: "Update cache", newEndpoints, newTracks }); this.cache[ids] = [newEndpoints, newTracks]; this.invalidateCache = false; } - console.log("Use cache"); - return this.cache[ids]; } } diff --git a/examples/ts-client/simple-app/src/main.ts b/examples/ts-client/simple-app/src/main.ts index 132e7e2e..9a1e6124 100644 --- a/examples/ts-client/simple-app/src/main.ts +++ b/examples/ts-client/simple-app/src/main.ts @@ -83,8 +83,7 @@ inputArray.forEach((input) => { }); }); -const TrackTypeValues = ["screensharing", "camera", "audio"] as const; -export type TrackType = (typeof TrackTypeValues)[number]; +export type TrackType = "screensharing" | "camera" | "audio"; export type PeerMetadata = { name: string; @@ -94,40 +93,7 @@ export type TrackMetadata = { active: boolean; }; -const isPeerMetadata = (input: unknown): input is PeerMetadata => { - return ( - typeof input === "object" && - input !== null && - "name" in input && - typeof input["name"] === "string" - ); -}; - -const isTrackType = (input: unknown): input is TrackType => - TrackTypeValues.includes(input as TrackType); - -const isTrackMetadata = (input: unknown): input is TrackMetadata => - typeof input === "object" && - input !== null && - "type" in input && - isTrackType(input.type) && - "active" in input && - typeof input.active === "boolean"; - -const trackMetadataParser = (input: unknown): TrackMetadata => { - if (isTrackMetadata(input)) return input; - throw Error("Invalid track metadata"); -}; - -const peerMetadataParser = (input: unknown): PeerMetadata => { - if (isPeerMetadata(input)) return input; - - throw Error("Invalid peer metadata"); -}; - const client: FishjamClient = new FishjamClient({ - peerMetadataParser, - trackMetadataParser, reconnect: true, }); @@ -157,34 +123,37 @@ client.on("trackAdded", (ctx) => { console.log({ name: "trackAdded", ctx }); }); -client.on("joined", (_peerId: string, peersInRoom: Peer[]) => { - console.log("Join success!"); - toastSuccess(`Joined room`); - const template = document.querySelector("#remote-peer-template-card")!; - const remotePeers = document.querySelector("#remote-peers")!; +client.on( + "joined", + (_peerId: string, peersInRoom: Peer[]) => { + console.log("Join success!"); + toastSuccess(`Joined room`); + const template = document.querySelector("#remote-peer-template-card")!; + const remotePeers = document.querySelector("#remote-peers")!; - (peersInRoom || []).forEach((peer: Peer) => { - // @ts-ignore - const clone = template.content.cloneNode(true); - const card = clone.firstElementChild; - card.dataset.peerId = peer.id; + (peersInRoom || []).forEach((peer: Peer) => { + // @ts-ignore + const clone = template.content.cloneNode(true); + const card = clone.firstElementChild; + card.dataset.peerId = peer.id; - const peerId = clone.querySelector(".remote-peer-template-id"); - peerId.innerHTML = peer.id; + const peerId = clone.querySelector(".remote-peer-template-id"); + peerId.innerHTML = peer.id; - clone.firstElementChild.dataset.peerId = peer.id; + clone.firstElementChild.dataset.peerId = peer.id; - document.querySelector(`div[data-peer-id="${peer.id}"`)?.remove(); - remotePeers.appendChild(clone); - }); -}); + document.querySelector(`div[data-peer-id="${peer.id}"`)?.remove(); + remotePeers.appendChild(clone); + }); + }, +); client.on("joinError", (metadata) => { console.log({ name: "joinError", metadata }); toastAlert("Join error"); }); -client.on("peerJoined", (peer: Peer) => { +client.on("peerJoined", (peer: Peer) => { console.log("Peer join success!"); const template = document.querySelector("#remote-peer-template-card")!; diff --git a/packages/react-client/src/hooks/useFishjamClientState.ts b/packages/react-client/src/hooks/useFishjamClientState.ts index 93aa11f8..1a14f3d9 100644 --- a/packages/react-client/src/hooks/useFishjamClientState.ts +++ b/packages/react-client/src/hooks/useFishjamClientState.ts @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef, useSyncExternalStore } from "react"; -import type { Component, Endpoint, MessageEvents, Peer, FishjamClient } from "@fishjam-cloud/ts-client"; +import type { Component, MessageEvents, Peer, FishjamClient } from "@fishjam-cloud/ts-client"; import type { PeerId, PeerMetadata, TrackMetadata } from "../types/internal"; const eventNames = [ @@ -43,9 +43,9 @@ const eventNames = [ ] as const satisfies (keyof MessageEvents)[]; export interface FishjamClientState { - peers: Record; + peers: Record>; components: Record; - localPeer: Endpoint | null; + localPeer: Peer | null; isReconnecting: boolean; } diff --git a/packages/react-client/src/hooks/usePeers.ts b/packages/react-client/src/hooks/usePeers.ts index 01b594bc..7f5926f9 100644 --- a/packages/react-client/src/hooks/usePeers.ts +++ b/packages/react-client/src/hooks/usePeers.ts @@ -1,5 +1,5 @@ -import type { Component, Endpoint, Peer, TrackContext } from "@fishjam-cloud/ts-client"; -import type { FishjamPeerMetadata, PeerState, TrackId, TrackMetadata } from "../types/internal"; +import type { Component, Endpoint, FishjamTrackContext, Peer } from "@fishjam-cloud/ts-client"; +import type { PeerMetadata, PeerState, TrackId, TrackMetadata } from "../types/internal"; import type { PeerWithTracks, Track } from "../types/public"; import { useFishjamContext } from "./useFishjamContext"; @@ -14,9 +14,9 @@ function getPeerWithDistinguishedTracks(peerState: PeerState): PeerWithTracks { return { ...peerState, cameraTrack, microphoneTrack, screenShareVideoTrack, screenShareAudioTrack }; } -function trackContextToTrack(track: TrackContext): Track { +function trackContextToTrack(track: FishjamTrackContext): Track { return { - metadata: track.metadata as TrackMetadata, + metadata: track.metadata, trackId: track.trackId, stream: track.stream, simulcastConfig: track.simulcastConfig ?? null, @@ -26,14 +26,14 @@ function trackContextToTrack(track: TrackContext): Track { }; } -function endpointToPeerState(peer: Peer | Component | Endpoint): PeerState { +function endpointToPeerState(peer: Peer | Component | Endpoint): PeerState { const tracks = [...peer.tracks].reduce( - (acc, [, track]) => ({ ...acc, [track.trackId]: trackContextToTrack(track) }), + (acc, [, track]) => ({ ...acc, [track.trackId]: trackContextToTrack(track as FishjamTrackContext) }), {} as Record, ); return { - metadata: peer.metadata as FishjamPeerMetadata, + metadata: peer.metadata as Peer["metadata"], id: peer.id, tracks, }; diff --git a/packages/react-client/src/hooks/useScreenShare.ts b/packages/react-client/src/hooks/useScreenShare.ts index 32b13d1f..6e14a402 100644 --- a/packages/react-client/src/hooks/useScreenShare.ts +++ b/packages/react-client/src/hooks/useScreenShare.ts @@ -25,7 +25,6 @@ export const useScreenShareManager = ({ const stream = state.stream ?? null; const [videoTrack, audioTrack] = stream ? getTracksFromStream(stream) : [null, null]; - // @ts-ignore const getDisplayName = () => fishjamClient.getLocalPeer()?.metadata?.peer?.displayName; const startStreaming: ScreenshareApi["startStreaming"] = async (props) => { diff --git a/packages/react-client/src/hooks/useTrackManager.ts b/packages/react-client/src/hooks/useTrackManager.ts index bcc26235..6acc32c4 100644 --- a/packages/react-client/src/hooks/useTrackManager.ts +++ b/packages/react-client/src/hooks/useTrackManager.ts @@ -63,7 +63,6 @@ export const useTrackManager = ({ // see `getRemoteOrLocalTrackContext()` explanation setCurrentTrackId(media.track.id); - // @ts-ignore const displayName = tsClient.getLocalPeer()?.metadata?.peer?.displayName; const deviceType = getDeviceType(mediaManager); diff --git a/packages/react-client/src/types/internal.ts b/packages/react-client/src/types/internal.ts index bf0e364d..e032a776 100644 --- a/packages/react-client/src/types/internal.ts +++ b/packages/react-client/src/types/internal.ts @@ -1,20 +1,16 @@ import type { DeviceType } from "../DeviceManager"; import type { StartStreamingProps, Track, TrackMiddleware, TracksMiddleware } from "./public"; +import type { Peer } from "@fishjam-cloud/ts-client"; export type TrackId = string; export type PeerId = string; export type PeerState = { id: PeerId; - metadata?: FishjamPeerMetadata; + metadata?: Peer["metadata"]; tracks: Record; }; -export type FishjamPeerMetadata = { - peer: PeerMetadata; - server?: Record; -}; - export type PeerMetadata = { displayName?: string; }; diff --git a/packages/react-client/src/utils/track.ts b/packages/react-client/src/utils/track.ts index 781109a3..c0d47125 100644 --- a/packages/react-client/src/utils/track.ts +++ b/packages/react-client/src/utils/track.ts @@ -26,19 +26,15 @@ const getRemoteOrLocalTrackContext = ( return trackByLocalId ? trackByLocalId : null; }; -const getTrackFromContext = (context: TrackContext): Track => { - return { - // todo typescript client should parse this metadata - // @ts-ignore - metadata: context.metadata as TrackMetadata, // todo parse metadata - trackId: context.trackId, - stream: context.stream, - simulcastConfig: context.simulcastConfig || null, - encoding: context.encoding || null, - vadStatus: context.vadStatus, - track: context.track, - }; -}; +const getTrackFromContext = (context: TrackContext): Track => ({ + metadata: context.metadata as TrackMetadata, + trackId: context.trackId, + stream: context.stream, + simulcastConfig: context.simulcastConfig || null, + encoding: context.encoding || null, + vadStatus: context.vadStatus, + track: context.track, +}); export const getRemoteOrLocalTrack = ( tsClient: FishjamClient, diff --git a/packages/ts-client/src/FishjamClient.ts b/packages/ts-client/src/FishjamClient.ts index 4205a5a5..1e995bc1 100644 --- a/packages/ts-client/src/FishjamClient.ts +++ b/packages/ts-client/src/FishjamClient.ts @@ -1,11 +1,13 @@ import type { BandwidthLimit, Encoding, + EncodingReason, Endpoint, SerializedMediaEvent, SimulcastConfig, TrackBandwidthLimit, TrackContext, + VadStatus, WebRTCEndpointEvents, } from './webrtc'; import { WebRTCEndpoint } from './webrtc'; @@ -20,13 +22,37 @@ import { connectEventsHandler } from './connectEventsHandler'; const STATISTICS_INTERVAL = 10_000; -export type Peer = Endpoint & { type: 'webrtc' }; +interface MyTrackContextEvents { + encodingChanged: (context: FishjamTrackContext) => void; + voiceActivityChanged: (context: FishjamTrackContext) => void; +} + +export interface FishjamTrackContext extends TypedEmitter>> { + readonly track: MediaStreamTrack | null; + readonly stream: MediaStream | null; + readonly endpoint: Endpoint; + readonly trackId: string; + readonly simulcastConfig?: SimulcastConfig; + readonly metadata?: Metadata; + readonly maxBandwidth?: TrackBandwidthLimit; + readonly vadStatus: VadStatus; + readonly encoding?: Encoding; + readonly encodingReason?: EncodingReason; +} + +export type Peer = { + id: string; + type: string; + metadata?: PeerServerMetadata; + tracks: Map>; +}; export type Component = Omit & { type: 'recording' | 'hls' | 'file' | 'rtsp' | 'sip'; }; -const isPeer = (endpoint: Endpoint): endpoint is Peer => endpoint.type === 'webrtc' || endpoint.type === 'exwebrtc'; +const isPeer = (endpoint: Endpoint): endpoint is Peer => + endpoint.type === 'webrtc' || endpoint.type === 'exwebrtc'; const isComponent = (endpoint: Endpoint): endpoint is Component => endpoint.type === 'recording' || @@ -37,10 +63,15 @@ const isComponent = (endpoint: Endpoint): endpoint is Component => const WEBSOCKET_PATH = 'socket/peer/websocket'; +export type PeerServerMetadata = { + peer: PeerMetadata; + server?: Record; +}; + /** * Events emitted by the client with their arguments. */ -export interface MessageEvents { +export interface MessageEvents { /** * Emitted when connect method invoked * @@ -89,7 +120,7 @@ export interface MessageEvents { /** * Called when peer was accepted. */ - joined: (peerId: string, peers: Peer[], components: Component[]) => void; + joined: (peerId: string, peers: Peer[], components: Component[]) => void; /** * Called when peer was not accepted @@ -103,40 +134,40 @@ export interface MessageEvents { * This callback is always called after {@link MessageEvents.trackAdded}. * It informs user that data related to the given track arrives and can be played or displayed. */ - trackReady: (ctx: TrackContext) => void; + trackReady: (ctx: FishjamTrackContext) => void; /** * Called each time the peer which was already in the room, adds new track. Fields track and stream will be set to null. * These fields will be set to non-null value in {@link MessageEvents.trackReady} */ - trackAdded: (ctx: TrackContext) => void; + trackAdded: (ctx: FishjamTrackContext) => void; /** * Called when some track will no longer be sent. * * It will also be called before {@link MessageEvents.peerLeft} for each track of this peer. */ - trackRemoved: (ctx: TrackContext) => void; + trackRemoved: (ctx: FishjamTrackContext) => void; /** * Called each time peer has its track metadata updated. */ - trackUpdated: (ctx: TrackContext) => void; + trackUpdated: (ctx: FishjamTrackContext) => void; /** * Called each time new peer joins the room. */ - peerJoined: (peer: Peer) => void; + peerJoined: (peer: Peer) => void; /** * Called each time peer leaves the room. */ - peerLeft: (peer: Peer) => void; + peerLeft: (peer: Peer) => void; /** * Called each time peer has its metadata updated. */ - peerUpdated: (peer: Peer) => void; + peerUpdated: (peer: Peer) => void; /** * Called each time new peer joins the room. @@ -166,7 +197,10 @@ export interface MessageEvents { * @param enabledTracks - list of tracks which will be sent to client from SFU * @param disabledTracks - list of tracks which will not be sent to client from SFU */ - tracksPriorityChanged: (enabledTracks: TrackContext[], disabledTracks: TrackContext[]) => void; + tracksPriorityChanged: ( + enabledTracks: FishjamTrackContext[], + disabledTracks: FishjamTrackContext[], + ) => void; /** * Called every time the server estimates client's bandiwdth. @@ -205,17 +239,10 @@ export interface ConnectConfig { url: string; } -export type CreateConfig = { - peerMetadataParser?: MetadataParser; - trackMetadataParser?: MetadataParser; +export type CreateConfig = { reconnect?: ReconnectConfig | boolean; }; -export type FishjamMetadata = { - peer?: Metadata; - server?: Record; -}; - /** * FishjamClient is the main class to interact with Fishjam. * @@ -250,12 +277,9 @@ export type FishjamMetadata = { * }); * ``` */ - -export type MetadataParser = (rawMetadata: unknown) => ParsedMetadata; - export class FishjamClient extends (EventEmitter as { - new (): TypedEmitter>; -}) { + new (): TypedEmitter>>; +}) { private websocket: WebSocket | null = null; private webrtc: WebRTCEndpoint | null = null; private removeEventListeners: (() => void) | null = null; @@ -268,13 +292,8 @@ export class FishjamClient extends (EventEmitter as private sendStatisticsInterval: NodeJS.Timeout | undefined = undefined; - private readonly peerMetadataParser: MetadataParser; - private readonly trackMetadataParser: MetadataParser; - - constructor(config?: CreateConfig) { + constructor(config?: CreateConfig) { super(); - this.peerMetadataParser = config?.peerMetadataParser ?? ((x) => x as PeerMetadata); - this.trackMetadataParser = config?.trackMetadataParser ?? ((x) => x as TrackMetadata); this.reconnectManager = new ReconnectManager( this, (peerMetadata) => this.initConnection(peerMetadata), @@ -410,14 +429,14 @@ export class FishjamClient extends (EventEmitter as * client.setTargetTrackEncoding(trackId, encoding); * } */ - getRemoteTracks(): Readonly> { - return this.webrtc?.getRemoteTracks() ?? {}; + getRemoteTracks(): Readonly>> { + return (this.webrtc?.getRemoteTracks() as Record>) ?? {}; } /** * Returns a snapshot of currently received remote peers. */ - public getRemotePeers(): Record { + public getRemotePeers(): Record> { return Object.entries(this.webrtc?.getRemoteEndpoints() ?? {}).reduce( (acc, [id, peer]) => (isPeer(peer) ? { ...acc, [id]: peer } : acc), {}, @@ -431,8 +450,8 @@ export class FishjamClient extends (EventEmitter as ); } - public getLocalPeer(): Endpoint | null { - return this.webrtc?.getLocalEndpoint() || null; + public getLocalPeer(): Peer | null { + return (this.webrtc?.getLocalEndpoint() as Peer) || null; } public getBandwidthEstimation(): bigint { @@ -450,7 +469,9 @@ export class FishjamClient extends (EventEmitter as }); this.webrtc?.on('connected', async (peerId: string, endpointsInRoom: Endpoint[]) => { - const peers = endpointsInRoom.filter((endpoint) => isPeer(endpoint)).map((peer) => peer as Peer); + const peers = endpointsInRoom + .filter((endpoint) => isPeer(endpoint)) + .map((peer) => peer as Peer); const components = endpointsInRoom .filter((endpoint) => isComponent(endpoint)) @@ -470,7 +491,7 @@ export class FishjamClient extends (EventEmitter as }); this.webrtc?.on('endpointAdded', (endpoint: Endpoint) => { if (isPeer(endpoint)) { - this.emit('peerJoined', endpoint); + this.emit('peerJoined', endpoint as Peer); } if (isComponent(endpoint)) { this.emit('componentAdded', endpoint); @@ -478,7 +499,7 @@ export class FishjamClient extends (EventEmitter as }); this.webrtc?.on('endpointRemoved', (endpoint: Endpoint) => { if (isPeer(endpoint)) { - this.emit('peerLeft', endpoint); + this.emit('peerLeft', endpoint as Peer); } if (isComponent(endpoint)) { this.emit('componentRemoved', endpoint); @@ -486,7 +507,7 @@ export class FishjamClient extends (EventEmitter as }); this.webrtc?.on('endpointUpdated', (endpoint: Endpoint) => { if (isPeer(endpoint)) { - this.emit('peerUpdated', endpoint); + this.emit('peerUpdated', endpoint as Peer); } if (isComponent(endpoint)) { this.emit('componentUpdated', endpoint); @@ -495,26 +516,30 @@ export class FishjamClient extends (EventEmitter as this.webrtc?.on('trackReady', (ctx: TrackContext) => { if (!isPeer(ctx.endpoint)) return; - this.emit('trackReady', ctx); + this.emit('trackReady', ctx as FishjamTrackContext); }); this.webrtc?.on('trackAdded', (ctx: TrackContext) => { if (!isPeer(ctx.endpoint)) return; - this.emit('trackAdded', ctx); + this.emit('trackAdded', ctx as FishjamTrackContext); }); this.webrtc?.on('trackRemoved', (ctx: TrackContext) => { if (!isPeer(ctx.endpoint)) return; - this.emit('trackRemoved', ctx); + this.emit('trackRemoved', ctx as FishjamTrackContext); ctx.removeAllListeners(); }); this.webrtc?.on('trackUpdated', (ctx: TrackContext) => { if (!isPeer(ctx.endpoint)) return; - this.emit('trackUpdated', ctx); + this.emit('trackUpdated', ctx as FishjamTrackContext); }); this.webrtc?.on('tracksPriorityChanged', (enabledTracks, disabledTracks) => { - this.emit('tracksPriorityChanged', enabledTracks, disabledTracks); + this.emit( + 'tracksPriorityChanged', + enabledTracks as FishjamTrackContext[], + disabledTracks as FishjamTrackContext[], + ); }); this.webrtc?.on('signalingError', (error) => { this.emit('joinError', error); diff --git a/packages/ts-client/src/index.ts b/packages/ts-client/src/index.ts index ef36934f..d0f262e2 100644 --- a/packages/ts-client/src/index.ts +++ b/packages/ts-client/src/index.ts @@ -1,4 +1,4 @@ -export type { Peer, Component, ConnectConfig, CreateConfig, MessageEvents } from './FishjamClient'; +export type { Peer, Component, ConnectConfig, CreateConfig, MessageEvents, FishjamTrackContext } from './FishjamClient'; export type { ReconnectConfig, ReconnectionStatus } from './reconnection'; diff --git a/packages/ts-client/src/webrtc/internal.ts b/packages/ts-client/src/webrtc/internal.ts index deec324c..65457df4 100644 --- a/packages/ts-client/src/webrtc/internal.ts +++ b/packages/ts-client/src/webrtc/internal.ts @@ -15,9 +15,8 @@ import type { export const isTrackKind = (kind: string): kind is TrackKind => kind === 'audio' || kind === 'video'; -// todo simplify type export class TrackContextImpl - extends (EventEmitter as { new (): TypedEmitter> }) + extends (EventEmitter as new () => TypedEmitter>) implements TrackContext { endpoint: Endpoint; diff --git a/packages/ts-client/src/webrtc/tracks/Remote.ts b/packages/ts-client/src/webrtc/tracks/Remote.ts index b7da7a04..e25a380b 100644 --- a/packages/ts-client/src/webrtc/tracks/Remote.ts +++ b/packages/ts-client/src/webrtc/tracks/Remote.ts @@ -87,8 +87,7 @@ export class Remote { tracks: new Map(), }; - // mutation in place - this.updateEndpointMetadata(newEndpoint, endpoint?.metadata); + newEndpoint.metadata = endpoint?.metadata; this.addEndpoint(newEndpoint); this.addTracks(newEndpoint.id, endpoint.tracks, endpoint.trackIdToMetadata); @@ -106,17 +105,11 @@ export class Remote { const endpoint: EndpointWithTrackContext | undefined = this.remoteEndpoints[data.id]; if (!endpoint) throw new Error(`Endpoint ${data.id} not found`); - // mutation in place - this.updateEndpointMetadata(endpoint, data.metadata); + endpoint.metadata = data.metadata; this.emit('endpointUpdated', endpoint); }; - // todo inline - private updateEndpointMetadata = (endpoint: EndpointWithTrackContext, metadata: unknown) => { - endpoint.metadata = metadata; - }; - public removeRemoteEndpoint = (endpointId: EndpointId) => { const endpoint: EndpointWithTrackContext | undefined = this.remoteEndpoints[endpointId]; if (!endpoint) throw new Error(`Endpoint ${endpointId} not found`); @@ -140,16 +133,11 @@ export class Remote { const remoteTrack = this.remoteTracks[trackId]; if (!remoteTrack) throw new Error(`Track ${trackId} not found`); - this.updateTrackMetadata(remoteTrack.trackContext, data.metadata); + remoteTrack.trackContext.metadata = data.metadata; this.emit('trackUpdated', remoteTrack.trackContext); }; - // todo inline - private updateTrackMetadata = (trackContext: TrackContextImpl, trackMetadata: unknown) => { - trackContext.metadata = trackMetadata; - }; - public disableRemoteTrackEncoding = (trackId: TrackId, encoding: Encoding) => { const remoteTrack = this.remoteTracks[trackId]; if (!remoteTrack) throw new Error(`Track ${trackId} not found`); diff --git a/packages/ts-client/src/webrtc/webRTCEndpoint.ts b/packages/ts-client/src/webrtc/webRTCEndpoint.ts index 5413bcd9..2700f3c3 100644 --- a/packages/ts-client/src/webrtc/webRTCEndpoint.ts +++ b/packages/ts-client/src/webrtc/webRTCEndpoint.ts @@ -24,9 +24,7 @@ import { ConnectionManager } from './ConnectionManager'; /** * Main class that is responsible for connecting to the RTC Engine, sending and receiving media. */ -export class WebRTCEndpoint extends (EventEmitter as { - new (): TypedEmitter>; -}) { +export class WebRTCEndpoint extends (EventEmitter as new () => TypedEmitter>) { private readonly localTrackManager: LocalTrackManager; private readonly remote: Remote; private readonly local: Local; diff --git a/packages/ts-client/tests/events/encodingSwitchedEvent.test.ts b/packages/ts-client/tests/events/encodingSwitchedEvent.test.ts index 0843fdd8..3086c3a7 100644 --- a/packages/ts-client/tests/events/encodingSwitchedEvent.test.ts +++ b/packages/ts-client/tests/events/encodingSwitchedEvent.test.ts @@ -39,9 +39,9 @@ it('Changing track encoding when endpoint exist but track does not exist', () => // When const encodingUpdatedEvent = createEncodingSwitchedEvent(endpointId, notExistingTrackId, 'm'); - expect(() => webRTCEndpoint.receiveMediaEvent(JSON.stringify(encodingUpdatedEvent))) - .rejects // todo change this error in production code - .toThrow(`Track ${notExistingTrackId} not found`); + expect(() => webRTCEndpoint.receiveMediaEvent(JSON.stringify(encodingUpdatedEvent))).rejects.toThrow( + `Track ${notExistingTrackId} not found`, + ); }); it('Changing track encoding when endpoint does not exist but track exist in other endpoint', () => { diff --git a/packages/ts-client/tests/events/trackAddedEvent.test.ts b/packages/ts-client/tests/events/trackAddedEvent.test.ts index 89ff7889..8508167d 100644 --- a/packages/ts-client/tests/events/trackAddedEvent.test.ts +++ b/packages/ts-client/tests/events/trackAddedEvent.test.ts @@ -125,6 +125,6 @@ it('tracksAdded -> offerData with one track -> handle sdpAnswer data with one vi // Then const midToTrackId = webRTCEndpoint['local']['getMidToTrackId'](); - // TODO this function should return 1 if a user wants to add local track + // midToTrackId?.size should be undefined because the local peer doesn't offer anything expect(midToTrackId?.size).toBe(undefined); }); diff --git a/packages/ts-client/tests/mocks.ts b/packages/ts-client/tests/mocks.ts index aea060a7..1976cf2a 100644 --- a/packages/ts-client/tests/mocks.ts +++ b/packages/ts-client/tests/mocks.ts @@ -34,7 +34,7 @@ export const mockRTCPeerConnection = (): { }; if (init?.direction === 'sendonly') { - sender.track = typeof trackOrKind !== 'string' ? trackOrKind : { id: 'someTrackId' }; // todo generate unique UUID + sender.track = typeof trackOrKind !== 'string' ? trackOrKind : { id: 'someTrackId' }; } senders.push(sender);