import { makeFakeMessage } from '../fixtures/chatFixtures'; import { HMSActions, IHMSStore, HMSPeer, HMSRoom, HMSTrackSource, HMSRoomState, HMSMessageInput, } from '@100mslive/hms-video-store'; import { HMSAudioTrackSettings, HMSVideoTrackSettings, HMSConfig, HMSPreferredSimulcastLayer } from '@100mslive/hms-video'; /* This is a dummy bridge with no connected backend. It can be used for storybook or writing functional tests. */ export class StoryBookSDK implements Partial { private readonly store: IHMSStore; private videoURLs: string[] = []; private dummyTrackURLs: Record = {}; private counter: number = 100; private localPeer?: HMSPeer; constructor(store: IHMSStore) { this.store = store; } setPreferredLayer(trackId: string, layer: HMSPreferredSimulcastLayer): Promise { throw new Error('Method not implemented.'); } setVolume(value: number, trackId?: string): Promise { throw new Error('Method not implemented.'); } setOutputDevice(deviceId: string) { throw new Error('Method not implemented'); } setOutputVolume(volume: number) { throw new Error('Method not implemented'); } addTrack(track: MediaStreamTrack, type: HMSTrackSource): Promise { throw new Error('Method not implemented.'); } removeTrack(trackId: string): Promise { throw new Error('Method not implemented.'); } setEnabledTrack(trackId: string, enabled: boolean): Promise { throw new Error('Method not implemented.'); } setMessageRead(readStatus: boolean, messageId: string): void { this.store.setState(store => { if (messageId) { if (!store.messages.byID[messageId]) { return; } else { store.messages.byID[messageId].read = readStatus; } } else { store.messages.allIDs.forEach((id: string) => { store.messages.byID[id].read = readStatus; }); } }); } async preview(config: HMSConfig) { if (!config.authToken) { this.log('invalid params'); return; } this.log('User called preview'); this.store.setState(store => { store.room.roomState = HMSRoomState.Preview; this.localPeer = { name: config?.userName, isLocal: true, id: String(this.randomNumber()), auxiliaryTracks: [], }; store.room.peers.push(this.localPeer.id); store.peers[this.localPeer.id] = this.localPeer; }); } async join(...args: any[]) { const joinParams = args[0]; if (!(joinParams.username && joinParams.role && joinParams.roomId)) { this.log('invalid params'); return; } this.log('User joining room'); this.store.setState(store => { store.room.isConnected = true; store.room.id = joinParams.roomId; if (!this.localPeer) { this.localPeer = { name: joinParams?.username, roleName: joinParams?.roleName, isLocal: true, id: String(this.randomNumber()), auxiliaryTracks: [], }; store.room.peers.push(this.localPeer.id); store.peers[this.localPeer.id] = this.localPeer; } }); } async attachVideo( trackID: string, videoElement: HTMLVideoElement, ): Promise { if (this.dummyTrackURLs[trackID]) { videoElement.src = this.dummyTrackURLs[trackID]; } this.log('video attached'); } async leave(): Promise { this.log('user left room'); this.store.setState(store => { store.room.isConnected = false; }); } async detachVideo( trackID: string, videoElement: HTMLVideoElement, ): Promise { videoElement.srcObject = null; this.log('video removed'); } sendMessage(message: string | HMSMessageInput): void { this.store.setState(store => { const user = 'You'; const newMsg = makeFakeMessage( typeof message === 'string' ? message : message.message, user, ); store.messages.byID[newMsg.id] = newMsg; store.messages.allIDs.push(newMsg.id); }); this.log('message sent - ', message); } async setLocalAudioEnabled(enabled: boolean): Promise { this.log('set local audio enabled state - ', enabled); } async setLocalVideoEnabled(enabled: boolean): Promise { this.log('set local video enabled state - ', enabled); } async setScreenShareEnabled(enabled: boolean): Promise { this.log('set screenshare enabled state - ', enabled); } addTestRoom(room: Partial) { this.store.setState(store => { Object.assign(store.room, room); }); } addTestPeerAndSpeaker(peer: HMSPeer) { const randomURL = this.randomFromArray(this.videoURLs); const videoTrackID = String( this.videoURLs.indexOf(randomURL) || this.counter++, ); const audioTrackID = String(this.counter++); this.dummyTrackURLs[videoTrackID] = randomURL; peer.audioTrack = audioTrackID; peer.videoTrack = videoTrackID; this.store.setState(store => { store.peers[peer.id] = peer; store.room.peers.push(peer.id); store.speakers[audioTrackID] = { audioLevel: this.randomFromArray([0, 10, 20, 50, 70, 80, 100]), peerID: peer.id, trackID: audioTrackID, }; if (peer.audioTrack) { store.tracks[audioTrackID] = { enabled: this.randomFromArray([true, false]), id: audioTrackID, type: 'audio', source: 'regular' }; } if (peer.videoTrack) { store.tracks[videoTrackID] = { enabled: true, id: videoTrackID, type: 'video', source: 'regular' }; } }); } addTestVideoURLs(urls: string[]) { this.videoURLs = urls; } getRandomPeer(): HMSPeer { return this.randomFromArray(this.getPeers()); } getPeers(): HMSPeer[] { return Object.values(this.store.getState().peers); } private log(...args: any[]) { console.log('storybook sdk', ...args); } private randomUser() { return this.randomFromArray([ 'You', 'Tushar', 'Eswar', 'Aniket', 'Kshitiz', 'Sagar', ]); } private randomNumber() { return Number(Math.floor(Math.random() * 100000)); } private randomFromArray(arr: T[]) { return arr[Math.floor(Math.random() * arr.length)]; } async setAudioSettings(settings: HMSAudioTrackSettings): Promise {} async setVideoSettings(settings: HMSVideoTrackSettings): Promise {} }