openvidu-browser: add event maps to achieve typings for all Events

pull/681/head
pabloFuente 2022-01-10 12:46:39 +01:00
parent 777b329e9f
commit 82bd984bbe
7 changed files with 108 additions and 87 deletions

View File

@ -16,6 +16,9 @@
*/
import { Event as Event } from '../OpenViduInternal/Events/Event';
import { SessionEventMap } from '../OpenViduInternal/Events/EventMap/SessionEventMap';
import { StreamManagerEventMap } from '../OpenViduInternal/Events/EventMap/StreamManagerEventMap';
import EventEmitter = require('wolfy87-eventemitter');
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
@ -40,33 +43,21 @@ export abstract class EventDispatcher {
*
* @returns The EventDispatcher object
*/
abstract on(type: string, handler: (event: Event) => void): EventDispatcher;
abstract on<K extends keyof (SessionEventMap | StreamManagerEventMap)>(type: K, handler: (event: (SessionEventMap | StreamManagerEventMap)[K]) => void): this;
/**
* Adds function `handler` to handle event `type` just once. The handler will be automatically removed after first execution
*
* @returns The object that dispatched the event
*/
abstract once(type: string, handler: (event: Event) => void): EventDispatcher;
abstract once<K extends keyof (SessionEventMap | StreamManagerEventMap)>(type: K, handler: (event: (SessionEventMap | StreamManagerEventMap)[K]) => void): this;
/**
* Removes a `handler` from event `type`. If no handler is provided, all handlers will be removed from the event
*
* @returns The object that dispatched the event
*/
off(type: string, handler?: (event: Event) => void): EventDispatcher {
if (!handler) {
this.ee.removeAllListeners(type);
} else {
// Must remove internal arrow function handler paired with user handler
const arrowHandler = this.userHandlerArrowHandler.get(handler);
if (!!arrowHandler) {
this.ee.off(type, arrowHandler);
}
this.userHandlerArrowHandler.delete(handler);
}
return this;
}
abstract off<K extends keyof (SessionEventMap | StreamManagerEventMap)>(type: K, handler?: (event: (SessionEventMap | StreamManagerEventMap)[K]) => void): this;
/**
* @hidden
@ -104,4 +95,21 @@ export abstract class EventDispatcher {
return this;
}
/**
* @hidden
*/
offAux(type: string, handler?: (event: Event) => void): EventDispatcher {
if (!handler) {
this.ee.removeAllListeners(type);
} else {
// Must remove internal arrow function handler paired with user handler
const arrowHandler = this.userHandlerArrowHandler.get(handler);
if (!!arrowHandler) {
this.ee.off(type, arrowHandler);
}
this.userHandlerArrowHandler.delete(handler);
}
return this;
}
}

View File

@ -19,12 +19,10 @@ import { OpenVidu } from './OpenVidu';
import { Session } from './Session';
import { Stream } from './Stream';
import { StreamManager } from './StreamManager';
import { EventDispatcher } from './EventDispatcher';
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
import { Event } from '../OpenViduInternal/Events/Event';
import { PublisherEventMap } from '../OpenViduInternal/Events/EventMap/PublisherEventMap';
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
@ -214,8 +212,10 @@ export class Publisher extends StreamManager {
/**
* See [[EventDispatcher.on]]
*/
on(type: string, handler: (event: Event) => void): EventDispatcher {
super.on(type, handler);
on<K extends keyof PublisherEventMap>(type: K, handler: (event: PublisherEventMap[K]) => void): this {
super.on(<any>type, handler);
if (type === 'streamCreated') {
if (!!this.stream && this.stream.isLocalStreamPublished) {
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
@ -225,15 +225,6 @@ export class Publisher extends StreamManager {
});
}
}
if (type === 'remoteVideoPlaying') {
if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
this.videos[0].video.currentTime > 0 &&
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
}
}
if (type === 'accessAllowed') {
if (this.accessAllowed) {
this.emitEvent('accessAllowed', []);
@ -251,8 +242,10 @@ export class Publisher extends StreamManager {
/**
* See [[EventDispatcher.once]]
*/
once(type: string, handler: (event: Event) => void): Publisher {
super.once(type, handler);
once<K extends keyof PublisherEventMap>(type: K, handler: (event: PublisherEventMap[K]) => void): this {
super.once(<any>type, handler);
if (type === 'streamCreated') {
if (!!this.stream && this.stream.isLocalStreamPublished) {
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
@ -262,15 +255,6 @@ export class Publisher extends StreamManager {
});
}
}
if (type === 'remoteVideoPlaying') {
if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video &&
this.videos[0].video.currentTime > 0 &&
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
}
}
if (type === 'accessAllowed') {
if (this.accessAllowed) {
this.emitEvent('accessAllowed', []);
@ -284,6 +268,16 @@ export class Publisher extends StreamManager {
return this;
}
/**
* See [[EventDispatcher.off]]
*/
off<K extends keyof PublisherEventMap>(type: K, handler?: (event: PublisherEventMap[K]) => void): this {
super.off(<any>type, handler);
return this;
}
/**
* Replaces the current video or audio track with a different one. This allows you to replace an ongoing track with a different one
* without having to renegotiate the whole WebRTC connection (that is, initializing a new Publisher, unpublishing the previous one

View File

@ -29,10 +29,9 @@ import { SubscriberProperties } from '../OpenViduInternal/Interfaces/Public/Subs
import { RemoteConnectionOptions } from '../OpenViduInternal/Interfaces/Private/RemoteConnectionOptions';
import { LocalConnectionOptions } from '../OpenViduInternal/Interfaces/Private/LocalConnectionOptions';
import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions';
import { SessionEventMap } from '../OpenViduInternal/Events/EventMap/SessionEventMap';
import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent';
import { ExceptionEvent } from '../OpenViduInternal/Events/ExceptionEvent';
import { FilterEvent } from '../OpenViduInternal/Events/FilterEvent';
import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpeakingEvent';
import { RecordingEvent } from '../OpenViduInternal/Events/RecordingEvent';
import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
@ -63,25 +62,6 @@ const logger: OpenViduLogger = OpenViduLogger.getInstance();
*/
let platform: PlatformUtils;
export interface SessionEventMap {
connectionCreated: ConnectionEvent
connectionDestroyed: ConnectionEvent
connectionPropertyChanged: ConnectionPropertyChangedEvent
sessionDisconnected: SessionDisconnectedEvent
streamCreated: StreamEvent
streamDestroyed: StreamEvent
streamPropertyChanged: StreamPropertyChangedEvent
publisherStartSpeaking: PublisherSpeakingEvent
publisherStopSpeaking: PublisherSpeakingEvent
signal: SignalEvent
recordingStarted: RecordingEvent
recordingStopped: RecordingEvent
networkQualityLevelChanged: NetworkQualityLevelChangedEvent
reconnecting: never
reconnected: never
exception: ExceptionEvent
}
/**
* Represents a video call. It can also be seen as a videoconference room where multiple users can connect.
* Participants who publish their videos to a session can be seen by the rest of users connected to that specific session.
@ -665,7 +645,7 @@ export class Session extends EventDispatcher {
/**
* See [[EventDispatcher.on]]
*/
on<K extends keyof SessionEventMap>(type: K, handler: (event: SessionEventMap[K]) => void): this {
on<K extends keyof SessionEventMap>(type: K, handler: (event: SessionEventMap[K]) => void): this {
super.onAux(type, "Event '" + type + "' triggered by 'Session'", handler);
@ -739,7 +719,7 @@ export class Session extends EventDispatcher {
*/
off<K extends keyof SessionEventMap>(type: K, handler?: (event: SessionEventMap[K]) => void): this {
super.off(type, handler);
super.offAux(type, handler);
if (type === 'publisherStartSpeaking') {
// Check if Session object still has some listener for the event
@ -1041,7 +1021,6 @@ export class Session extends EventDispatcher {
*/
recvIceCandidate(event: { senderConnectionId: string, endpointName: string, sdpMLineIndex: number, sdpMid: string, candidate: string }): void {
const candidate: RTCIceCandidate = {
address: null,
candidate: event.candidate,
sdpMid: event.sdpMid,
sdpMLineIndex: event.sdpMLineIndex,

View File

@ -19,13 +19,13 @@ import { Stream } from './Stream';
import { Subscriber } from './Subscriber';
import { EventDispatcher } from './EventDispatcher';
import { StreamManagerVideo } from '../OpenViduInternal/Interfaces/Public/StreamManagerVideo';
import { Event } from '../OpenViduInternal/Events/Event';
import { StreamManagerEventMap } from '../OpenViduInternal/Events/EventMap/StreamManagerEventMap';
import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
import { ExceptionEvent, ExceptionEventName } from '../OpenViduInternal/Events/ExceptionEvent';
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
import { ExceptionEvent, ExceptionEventName } from '../OpenViduInternal/Events/ExceptionEvent';
/**
* @hidden
@ -145,18 +145,6 @@ export class StreamManager extends EventDispatcher {
this.canPlayListener = () => {
this.deactivateStreamPlayingEventExceptionTimeout();
if (this.remote) {
logger.info("Remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
} else {
if (!this.stream.displayMyRemote()) {
logger.info("Your local 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
} else {
logger.info("Your own remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
}
}
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
};
}
@ -164,9 +152,9 @@ export class StreamManager extends EventDispatcher {
/**
* See [[EventDispatcher.on]]
*/
on(type: string, handler: (event: Event) => void): EventDispatcher {
on<K extends keyof StreamManagerEventMap>(type: K, handler: (event: StreamManagerEventMap[K]) => void): this {
super.onAux(type, "Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler)
super.onAux(type, "Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler);
if (type === 'videoElementCreated') {
if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) {
@ -174,14 +162,13 @@ export class StreamManager extends EventDispatcher {
this.lazyLaunchVideoElementCreatedEvent = false;
}
}
if (type === 'streamPlaying' || type === 'videoPlaying') {
if (type === 'streamPlaying') {
if (this.videos[0] && this.videos[0].video &&
this.videos[0].video.currentTime > 0 &&
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
}
if (this.stream.hasAudio) {
@ -201,7 +188,7 @@ export class StreamManager extends EventDispatcher {
/**
* See [[EventDispatcher.once]]
*/
once(type: string, handler: (event: Event) => void): StreamManager {
once<K extends keyof StreamManagerEventMap>(type: K, handler: (event: StreamManagerEventMap[K]) => void): this {
super.onceAux(type, "Event '" + type + "' triggered once by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler);
@ -210,14 +197,13 @@ export class StreamManager extends EventDispatcher {
this.ee.emitEvent('videoElementCreated', [new VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]);
}
}
if (type === 'streamPlaying' || type === 'videoPlaying') {
if (type === 'streamPlaying') {
if (this.videos[0] && this.videos[0].video &&
this.videos[0].video.currentTime > 0 &&
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
}
if (this.stream.hasAudio) {
@ -237,9 +223,9 @@ export class StreamManager extends EventDispatcher {
/**
* See [[EventDispatcher.off]]
*/
off(type: string, handler?: (event: Event) => void): StreamManager {
off<K extends keyof StreamManagerEventMap>(type: K, handler?: (event: StreamManagerEventMap[K]) => void): this {
super.off(type, handler);
super.offAux(type, handler);
if (type === 'publisherStartSpeaking') {
// Both StreamManager and Session can have "publisherStartSpeaking" event listeners

View File

@ -0,0 +1,11 @@
import { StreamEvent } from '../StreamEvent';
import { StreamManagerEventMap } from './StreamManagerEventMap';
export interface PublisherEventMap extends StreamManagerEventMap {
streamCreated: StreamEvent;
streamDestroyed: StreamEvent;
accessAllowed: never;
accessDenied: never;
accessDialogOpened: never;
accessDialogClosed: never;
}

View File

@ -0,0 +1,29 @@
import { ConnectionEvent } from '../ConnectionEvent';
import { ConnectionPropertyChangedEvent } from '../ConnectionPropertyChangedEvent';
import { ExceptionEvent } from '../ExceptionEvent';
import { NetworkQualityLevelChangedEvent } from '../NetworkQualityLevelChangedEvent';
import { PublisherSpeakingEvent } from '../PublisherSpeakingEvent';
import { RecordingEvent } from '../RecordingEvent';
import { SessionDisconnectedEvent } from '../SessionDisconnectedEvent';
import { SignalEvent } from '../SignalEvent';
import { StreamEvent } from '../StreamEvent';
import { StreamPropertyChangedEvent } from '../StreamPropertyChangedEvent';
export interface SessionEventMap {
connectionCreated: ConnectionEvent;
connectionDestroyed: ConnectionEvent;
connectionPropertyChanged: ConnectionPropertyChangedEvent;
sessionDisconnected: SessionDisconnectedEvent;
streamCreated: StreamEvent;
streamDestroyed: StreamEvent;
streamPropertyChanged: StreamPropertyChangedEvent;
publisherStartSpeaking: PublisherSpeakingEvent;
publisherStopSpeaking: PublisherSpeakingEvent;
signal: SignalEvent;
recordingStarted: RecordingEvent;
recordingStopped: RecordingEvent;
networkQualityLevelChanged: NetworkQualityLevelChangedEvent;
reconnecting: never;
reconnected: never;
exception: ExceptionEvent;
}

View File

@ -0,0 +1,14 @@
import { PublisherSpeakingEvent } from '../PublisherSpeakingEvent';
import { StreamManagerEvent } from '../StreamManagerEvent';
import { StreamPropertyChangedEvent } from '../StreamPropertyChangedEvent';
import { VideoElementEvent } from '../VideoElementEvent';
export interface StreamManagerEventMap {
videoElementCreated: VideoElementEvent;
videoElementDestroyed: VideoElementEvent;
streamPlaying: StreamManagerEvent;
streamAudioVolumeChange: StreamManagerEvent;
streamPropertyChanged: StreamPropertyChangedEvent;
publisherStartSpeaking: PublisherSpeakingEvent;
publisherStopSpeaking: PublisherSpeakingEvent;
}