208 lines
6.5 KiB
TypeScript

import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MatIcon } from '@angular/material/icon';
import {
RecordingDeleteRequestedEvent,
RecordingStartRequestedEvent,
RecordingStopRequestedEvent,
ApiDirectiveModule,
ParticipantLeftEvent,
ParticipantModel,
OpenViduComponentsUiModule
} from 'openvidu-components-angular';
import { MeetChatPreferences, MeetRecordingPreferences, MeetVirtualBackgroundPreferences } from '@lib/typings/ce';
import { HttpService, WebComponentManagerService, ContextService, RoomService, SessionStorageService } from '../../services';
import { OpenViduMeetMessage, WebComponentEventType } from 'webcomponent/src/types/message.type';
@Component({
selector: 'app-video-room',
templateUrl: './video-room.component.html',
styleUrls: ['./video-room.component.scss'],
standalone: true,
imports: [OpenViduComponentsUiModule, ApiDirectiveModule, MatIcon]
})
export class VideoRoomComponent implements OnInit, OnDestroy {
roomId = '';
participantName = '';
token = '';
serverError = '';
loading = true;
chatPreferences: MeetChatPreferences = { enabled: true };
recordingPreferences: MeetRecordingPreferences = { enabled: true };
virtualBackgroundPreferences: MeetVirtualBackgroundPreferences = { enabled: true };
featureFlags = {
videoEnabled: true,
audioEnabled: true,
showMicrophone: true,
showCamera: true,
showScreenShare: true,
showPrejoin: true,
showChat: true,
showRecording: true,
showBackgrounds: true
};
constructor(
protected httpService: HttpService,
protected router: Router,
protected ctxService: ContextService,
protected roomService: RoomService,
protected wcManagerService: WebComponentManagerService,
protected sessionStorageService: SessionStorageService,
protected cdr: ChangeDetectorRef
) {}
async ngOnInit() {
try {
this.roomId = this.ctxService.getRoomId();
this.participantName = this.ctxService.getParticipantName();
if (this.ctxService.isEmbeddedMode()) {
this.featureFlags.showPrejoin = false;
}
// TODO: Apply room preferences from saved room using context service
// await this.loadRoomPreferences();
// TODO: Extract permissions from token and apply them to the component
this.applyParticipantPermissions();
} catch (error: any) {
console.error('Error fetching room preferences', error);
this.serverError = error.error.message || error.message || error.error;
}
this.loading = false;
}
ngOnDestroy(): void {
// Clean up the context service
// this.contextService.clearContext();
this.wcManagerService.stopCommandsListener();
}
async onTokenRequested(participantName: string) {
try {
if (this.ctxService.isStandaloneMode()) {
// As token is not provided, we need to set the participant name from
// ov-videoconference event
this.ctxService.setParticipantName(participantName);
}
this.token = this.ctxService.getToken();
} catch (error: any) {
console.error(error);
this.serverError = error.error;
}
this.loading = false;
this.cdr.detectChanges();
}
onParticipantConnected(event: ParticipantModel) {
const message: OpenViduMeetMessage = {
eventType: WebComponentEventType.LOCAL_PARTICIPANT_CONNECTED,
payload: {
roomId: event.getProperties().room?.name,
participantName: event.name
}
};
this.wcManagerService.sendMessageToParent(message);
}
onParticipantLeft(event: ParticipantLeftEvent) {
console.warn('Participant left the room. Redirecting to:');
const redirectURL = this.ctxService.getLeaveRedirectURL() || '/disconnected';
const isExternalURL = /^https?:\/\//.test(redirectURL);
const message: OpenViduMeetMessage = {
eventType: WebComponentEventType.LOCAL_PARTICIPANT_LEFT,
payload: {
roomId: event.roomName,
participantName: event.participantName
}
};
this.wcManagerService.sendMessageToParent(message);
this.sessionStorageService.removeModeratorSecret(event.roomName);
//if (this.contextService.isEmbeddedMode()) this.sendMessageToParent(event);
this.redirectTo(redirectURL, isExternalURL);
}
async onRecordingStartRequested(event: RecordingStartRequestedEvent) {
try {
const { roomName: roomId } = event;
await this.httpService.startRecording(roomId);
} catch (error) {
console.error(error);
}
}
async onRecordingStopRequested(event: RecordingStopRequestedEvent) {
try {
const { recordingId } = event;
if (!recordingId) throw new Error('Recording ID not found when stopping recording');
await this.httpService.stopRecording(recordingId);
} catch (error) {
console.error(error);
}
}
async onRecordingDeleteRequested(event: RecordingDeleteRequestedEvent) {
try {
const { recordingId } = event;
if (!recordingId) throw new Error('Recording ID not found when deleting recording');
await this.httpService.deleteRecording(recordingId);
} catch (error) {
console.error(error);
}
}
/**
* Loads the room preferences from the global preferences service and assigns them to the component.
*
* This method fetches the room preferences asynchronously and updates the component's properties
* based on the fetched preferences. It also updates the UI flags to show or hide certain features
* like chat, recording, and activity panel based on the preferences.
*
* @returns {Promise<void>} A promise that resolves when the room preferences have been loaded and applied.
*/
private async loadRoomPreferences() {
const preferences = await this.roomService.getRoomPreferences();
// Assign the preferences to the component
Object.assign(this, preferences);
this.featureFlags.showChat = this.chatPreferences.enabled;
this.featureFlags.showRecording = this.recordingPreferences.enabled;
this.featureFlags.showBackgrounds = this.virtualBackgroundPreferences.enabled;
}
/**
* Configures the feature flags based on the token permissions.
*
* This method checks the token permissions and sets the feature flags accordingly.
*/
private applyParticipantPermissions() {
if (this.featureFlags.showChat) {
this.featureFlags.showChat = this.ctxService.canChat();
}
if (this.featureFlags.showRecording) {
this.featureFlags.showRecording = this.ctxService.canRecord();
}
}
private redirectTo(url: string, isExternal: boolean) {
if (isExternal) {
console.log('Redirecting to external URL:', url);
window.location.href = url;
} else {
console.log('Redirecting to internal route:', url);
this.router.navigate([url], { replaceUrl: true });
}
}
}