diff --git a/README.md b/README.md index e64bece531..580bd1338a 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,8 @@ connect('ws://localhost:7800', token, { .on(RoomEvent.TrackSubscribed, handleTrackSubscribed) .on(RoomEvent.TrackUnsubscribed, handleTrackUnsubscribed) .on(RoomEvent.ActiveSpeakersChanged, handleActiveSpeakerChange) - .on(RoomEvent.Disconnected, handleDisconnect); + .on(RoomEvent.Disconnected, handleDisconnect) + .on(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnpublished); }); function handleTrackSubscribed( @@ -79,6 +80,14 @@ function handleTrackUnsubscribed( track.detach(); } +function handleLocalTrackUnpublished( + track: LocalTrackPublication, + participant: LocalParticipant, +) { + // when local tracks are ended, update UI to remove them from rendering + track.detach(); +} + function handleActiveSpeakerChange(speakers: Participant[]) { // show UI indicators when participant is speaking } diff --git a/src/room/Room.ts b/src/room/Room.ts index 065a0f828f..82b0d0965e 100644 --- a/src/room/Room.ts +++ b/src/room/Room.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events'; -import log from '../logger'; import { SignalClient, SignalOptions } from '../api/SignalClient'; +import log from '../logger'; import { DataPacket_Kind, ParticipantInfo, ParticipantInfo_State, Room as RoomModel, SpeakerInfo, UserPacket, @@ -18,6 +18,7 @@ import LocalParticipant from './participant/LocalParticipant'; import Participant from './participant/Participant'; import RemoteParticipant from './participant/RemoteParticipant'; import RTCEngine, { maxICEConnectTimeout } from './RTCEngine'; +import LocalTrackPublication from './track/LocalTrackPublication'; import { TrackCaptureDefaults, TrackPublishDefaults } from './track/options'; import RemoteTrackPublication from './track/RemoteTrackPublication'; import { Track } from './track/Track'; @@ -174,9 +175,12 @@ class Room extends EventEmitter { .on(ParticipantEvent.TrackUnmuted, (pub: TrackPublication) => { this.emit(RoomEvent.TrackUnmuted, pub, this.localParticipant); }) - .on(ParticipantEvent.LocalTrackPublished, (pub: TrackPublication) => { + .on(ParticipantEvent.LocalTrackPublished, (pub: LocalTrackPublication) => { this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant); }) + .on(ParticipantEvent.LocalTrackUnpublished, (pub: LocalTrackPublication) => { + this.emit(RoomEvent.LocalTrackUnpublished, pub, this.localParticipant); + }) .on(ParticipantEvent.MediaDevicesError, (e: Error) => { this.emit(RoomEvent.MediaDevicesError, e); }); diff --git a/src/room/events.ts b/src/room/events.ts index 7ae4874051..971e1e1cf1 100644 --- a/src/room/events.ts +++ b/src/room/events.ts @@ -103,12 +103,24 @@ export enum RoomEvent { TrackUnmuted = 'trackUnmuted', /** - * A track was published successfully + * A local track was published successfully. This event is helpful to know + * when to update your local UI with the newly published track. * * args: ([[LocalTrackPublication]], [[LocalParticipant]]) */ LocalTrackPublished = 'localTrackPublished', + /** + * A local track was unpublished. This event is helpful to know when to remove + * the local track from your UI. + * + * When a user stops sharing their screen by pressing "End" on the browser UI, + * this event will also fire. + * + * args: ([[LocalTrackPublication]], [[LocalParticipant]]) + */ + LocalTrackUnpublished = 'localTrackUnpublished', + /** * Active speakers changed. List of speakers are ordered by their audio level. * loudest speakers first. This will include the LocalParticipant too. @@ -181,6 +193,7 @@ export enum ParticipantEvent { TrackMuted = 'trackMuted', TrackUnmuted = 'trackUnmuted', LocalTrackPublished = 'localTrackPublished', + LocalTrackUnpublished = 'localTrackUnpublished', MetadataChanged = 'metadataChanged', ParticipantMetadataChanged = 'participantMetadataChanged', DataReceived = 'dataReceived', diff --git a/src/room/participant/LocalParticipant.ts b/src/room/participant/LocalParticipant.ts index 6dffb932cf..228685817e 100644 --- a/src/room/participant/LocalParticipant.ts +++ b/src/room/participant/LocalParticipant.ts @@ -321,6 +321,8 @@ export default class LocalParticipant extends Participant { break; } + this.emit(ParticipantEvent.LocalTrackUnpublished, publication); + return publication; }