fixed tests
This commit is contained in:
153
public/js/subscriber.ts
Normal file
153
public/js/subscriber.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { WebSocketClient, WebSocketClientStatusMapping } from './services/WebSocketClient.ts';
|
||||
import { UIController } from './services/UIController.ts';
|
||||
import { SubscriberRTCManager } from './services/SubscriberRTCManager.ts';
|
||||
import type { ISignalingMessage } from './interfaces/IWebRTCClient.ts';
|
||||
import { DisposableList } from '@techniker-me/tools';
|
||||
|
||||
class Subscriber {
|
||||
private readonly _disposables: DisposableList = new DisposableList();
|
||||
private wsClient: WebSocketClient;
|
||||
private uiController: UIController;
|
||||
private rtcManager: SubscriberRTCManager;
|
||||
private isConnected = false;
|
||||
private videoPlaceholder: HTMLElement | null;
|
||||
private remoteVideo: HTMLVideoElement | null;
|
||||
|
||||
constructor() {
|
||||
this.wsClient = new WebSocketClient('subscriber');
|
||||
this.uiController = new UIController('status', undefined, 'connectBtn', 'disconnectBtn');
|
||||
this.videoPlaceholder = document.getElementById('videoPlaceholder');
|
||||
this.remoteVideo = document.getElementById('remoteVideo') as HTMLVideoElement;
|
||||
|
||||
this.rtcManager = new SubscriberRTCManager(
|
||||
'remoteVideo',
|
||||
(stream) => this.onStreamReceived(stream),
|
||||
(state) => this.onConnectionStateChange(state)
|
||||
);
|
||||
|
||||
this.setupEventHandlers();
|
||||
this.setupWebSocketHandlers();
|
||||
}
|
||||
|
||||
private setupEventHandlers(): void {
|
||||
this.uiController.onButtonClick('connectBtn', () => this.connect());
|
||||
this.uiController.onButtonClick('disconnectBtn', () => this.disconnect());
|
||||
}
|
||||
|
||||
private setupWebSocketHandlers(): void {
|
||||
this._disposables.add(this.wsClient.status.subscribe((status) => {
|
||||
this.uiController.updateStatus(WebSocketClientStatusMapping.convertWebSocketClientStatusToWebSocketClientStatusType(status), status);
|
||||
}));
|
||||
|
||||
this.wsClient.onMessage('join', (message) => {
|
||||
this.uiController.updateStatus('Connected - Waiting for publisher', 'waiting');
|
||||
this.isConnected = true;
|
||||
this.uiController.setButtonStates(false, true);
|
||||
});
|
||||
|
||||
this.wsClient.onMessage('publisher-joined', (message) => {
|
||||
this.uiController.updateStatus('Publisher available - Requesting stream', 'waiting');
|
||||
});
|
||||
|
||||
this.wsClient.onMessage('publisher-left', (message) => {
|
||||
this.uiController.updateStatus('Publisher disconnected', 'disconnected');
|
||||
this.showVideoPlaceholder();
|
||||
});
|
||||
|
||||
this.wsClient.onMessage('offer', async (message) => {
|
||||
try {
|
||||
const answer = await this.rtcManager.handleOffer(message.data);
|
||||
const answerMessage: ISignalingMessage = {
|
||||
type: 'answer',
|
||||
data: answer,
|
||||
targetId: message.senderId
|
||||
};
|
||||
this.wsClient.sendMessage(answerMessage);
|
||||
|
||||
this.uiController.updateStatus('Connecting to stream...', 'waiting');
|
||||
} catch (error) {
|
||||
console.error('Error handling offer:', error);
|
||||
this.uiController.updateStatus('Failed to connect to stream', 'disconnected');
|
||||
}
|
||||
});
|
||||
|
||||
this.wsClient.onMessage('ice-candidate', async (message) => {
|
||||
if (message.data) {
|
||||
await this.rtcManager.handleIceCandidate(message.data);
|
||||
}
|
||||
});
|
||||
|
||||
this.rtcManager.setOnIceCandidate((candidate) => {
|
||||
const message: ISignalingMessage = {
|
||||
type: 'ice-candidate',
|
||||
data: candidate
|
||||
};
|
||||
this.wsClient.sendMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
private async connect(): Promise<void> {
|
||||
try {
|
||||
this.uiController.updateStatus('Connecting to server...', 'waiting');
|
||||
this.uiController.setButtonStates(false, false);
|
||||
|
||||
await this.wsClient.connect();
|
||||
} catch (error) {
|
||||
console.error('Error connecting:', error);
|
||||
this.uiController.updateStatus('Failed to connect to server', 'disconnected');
|
||||
this.uiController.setButtonStates(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private disconnect(): void {
|
||||
this.isConnected = false;
|
||||
this.rtcManager.disconnect();
|
||||
this.wsClient.disconnect();
|
||||
|
||||
this.uiController.updateStatus('Disconnected', 'disconnected');
|
||||
this.uiController.setButtonStates(true, false);
|
||||
this.showVideoPlaceholder();
|
||||
}
|
||||
|
||||
private onStreamReceived(stream: MediaStream): void {
|
||||
console.log('Stream received, showing video');
|
||||
this.uiController.updateStatus('Connected - Receiving stream', 'connected');
|
||||
this.hideVideoPlaceholder();
|
||||
}
|
||||
|
||||
private onConnectionStateChange(state: string): void {
|
||||
switch (state) {
|
||||
case 'connected':
|
||||
this.uiController.updateStatus('Connected - Receiving stream', 'connected');
|
||||
break;
|
||||
case 'connecting':
|
||||
this.uiController.updateStatus('Connecting to stream...', 'waiting');
|
||||
break;
|
||||
case 'disconnected':
|
||||
case 'failed':
|
||||
this.uiController.updateStatus('Connection lost', 'disconnected');
|
||||
this.showVideoPlaceholder();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private hideVideoPlaceholder(): void {
|
||||
if (this.videoPlaceholder) {
|
||||
this.videoPlaceholder.style.display = 'none';
|
||||
}
|
||||
if (this.remoteVideo) {
|
||||
this.remoteVideo.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
private showVideoPlaceholder(): void {
|
||||
if (this.videoPlaceholder) {
|
||||
this.videoPlaceholder.style.display = 'flex';
|
||||
}
|
||||
if (this.remoteVideo) {
|
||||
this.remoteVideo.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Subscriber();
|
||||
Reference in New Issue
Block a user