250 lines
7.2 KiB
TypeScript
250 lines
7.2 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { BehaviorSubject, Observable, combineLatest, map } from 'rxjs';
|
|
import { LoggerService } from 'openvidu-components-angular';
|
|
import {
|
|
MeetRoomPreferences,
|
|
GlobalPreferences,
|
|
OpenViduMeetPermissions,
|
|
ParticipantRole,
|
|
RecordingPermissions
|
|
} from '@lib/typings/ce';
|
|
import { GlobalPreferencesService } from '../global-preferences/global-preferences.service';
|
|
|
|
/**
|
|
* Interface that defines all available features in the application
|
|
*/
|
|
export interface ApplicationFeatures {
|
|
// Video Room Features
|
|
videoEnabled: boolean;
|
|
audioEnabled: boolean;
|
|
showMicrophone: boolean;
|
|
showCamera: boolean;
|
|
showScreenShare: boolean;
|
|
showPrejoin: boolean;
|
|
|
|
// Communication Features
|
|
showChat: boolean;
|
|
showRecording: boolean;
|
|
showBackgrounds: boolean;
|
|
|
|
// UI Features
|
|
showParticipantList: boolean;
|
|
showSettings: boolean;
|
|
showFullscreen: boolean;
|
|
|
|
// Admin Features
|
|
canModerateRoom: boolean;
|
|
canManageRecordings: boolean;
|
|
canAccessConsole: boolean;
|
|
|
|
// Recording Features
|
|
canDeleteRecordings: boolean;
|
|
canRetrieveRecordings: boolean;
|
|
}
|
|
|
|
/**
|
|
* Base configuration for default features
|
|
*/
|
|
const DEFAULT_FEATURES: ApplicationFeatures = {
|
|
videoEnabled: true,
|
|
audioEnabled: true,
|
|
showMicrophone: true,
|
|
showCamera: true,
|
|
showScreenShare: true,
|
|
showPrejoin: true,
|
|
showChat: true,
|
|
showRecording: true,
|
|
showBackgrounds: true,
|
|
showParticipantList: true,
|
|
showSettings: true,
|
|
showFullscreen: true,
|
|
canModerateRoom: false,
|
|
canManageRecordings: false,
|
|
canAccessConsole: false,
|
|
canDeleteRecordings: false,
|
|
canRetrieveRecordings: false
|
|
};
|
|
|
|
/**
|
|
* Centralized service to manage feature configuration
|
|
* based on global preferences, room preferences, and participant permissions
|
|
*/
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class FeatureConfigurationService {
|
|
protected log;
|
|
|
|
// Subjects to handle reactive state
|
|
protected globalPreferencesSubject = new BehaviorSubject<GlobalPreferences | null>(null);
|
|
protected roomPreferencesSubject = new BehaviorSubject<MeetRoomPreferences | null>(null);
|
|
protected participantPermissionsSubject = new BehaviorSubject<OpenViduMeetPermissions | null>(null);
|
|
protected recordingPermissionsSubject = new BehaviorSubject<RecordingPermissions | null>(null);
|
|
protected participantRoleSubject = new BehaviorSubject<ParticipantRole | null>(null);
|
|
|
|
// Observable that combines all configurations
|
|
public readonly features$: Observable<ApplicationFeatures>;
|
|
|
|
constructor(
|
|
protected loggerService: LoggerService,
|
|
protected globalPreferencesService: GlobalPreferencesService
|
|
) {
|
|
this.log = this.loggerService.get('OpenVidu Meet - FeatureConfigurationService');
|
|
|
|
// Configure the combined observable
|
|
this.features$ = combineLatest([
|
|
this.globalPreferencesSubject.asObservable(),
|
|
this.roomPreferencesSubject.asObservable(),
|
|
this.participantPermissionsSubject.asObservable(),
|
|
this.recordingPermissionsSubject.asObservable(),
|
|
this.participantRoleSubject.asObservable()
|
|
]).pipe(
|
|
map(([globalPrefs, roomPrefs, participantPerms, recordingPerms, role]) =>
|
|
this.calculateFeatures(globalPrefs, roomPrefs, participantPerms, recordingPerms, role)
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Updates global preferences
|
|
*/
|
|
setGlobalPreferences(preferences: GlobalPreferences | null): void {
|
|
this.log.d('Updating global preferences', preferences);
|
|
this.globalPreferencesSubject.next(preferences);
|
|
}
|
|
|
|
/**
|
|
* Updates room preferences
|
|
*/
|
|
setRoomPreferences(preferences: MeetRoomPreferences | null): void {
|
|
this.log.d('Updating room preferences', preferences);
|
|
this.roomPreferencesSubject.next(preferences);
|
|
}
|
|
|
|
/**
|
|
* Updates participant permissions
|
|
*/
|
|
setParticipantPermissions(permissions: OpenViduMeetPermissions | null): void {
|
|
this.log.d('Updating participant permissions', permissions);
|
|
this.participantPermissionsSubject.next(permissions);
|
|
}
|
|
|
|
/**
|
|
* Updates recording permissions
|
|
*/
|
|
setRecordingPermissions(permissions: RecordingPermissions | null): void {
|
|
this.log.d('Updating recording permissions', permissions);
|
|
this.recordingPermissionsSubject.next(permissions);
|
|
}
|
|
|
|
/**
|
|
* Updates participant role
|
|
*/
|
|
setParticipantRole(role: ParticipantRole | null): void {
|
|
this.log.d('Updating participant role', role);
|
|
this.participantRoleSubject.next(role);
|
|
}
|
|
|
|
/**
|
|
* Gets the current feature configuration synchronously
|
|
*/
|
|
getCurrentFeatures(): ApplicationFeatures {
|
|
return this.calculateFeatures(
|
|
this.globalPreferencesSubject.value,
|
|
this.roomPreferencesSubject.value,
|
|
this.participantPermissionsSubject.value,
|
|
this.recordingPermissionsSubject.value,
|
|
this.participantRoleSubject.value
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Checks if a specific feature is enabled
|
|
*/
|
|
isFeatureEnabled(featureName: keyof ApplicationFeatures): boolean {
|
|
return this.getCurrentFeatures()[featureName];
|
|
}
|
|
|
|
/**
|
|
* Core logic to calculate features based on all configurations
|
|
*/
|
|
protected calculateFeatures(
|
|
globalPrefs: GlobalPreferences | null,
|
|
roomPrefs: MeetRoomPreferences | null,
|
|
participantPerms: OpenViduMeetPermissions | null,
|
|
recordingPerms: RecordingPermissions | null,
|
|
role: ParticipantRole | null
|
|
): ApplicationFeatures {
|
|
// Start with default configuration
|
|
const features: ApplicationFeatures = { ...DEFAULT_FEATURES };
|
|
|
|
// Apply global preferences restrictions
|
|
if (globalPrefs) {
|
|
}
|
|
|
|
// Apply room configurations
|
|
if (roomPrefs) {
|
|
features.showChat = roomPrefs.chatPreferences.enabled;
|
|
features.showRecording = roomPrefs.recordingPreferences.enabled && role === ParticipantRole.MODERATOR;
|
|
features.showBackgrounds = roomPrefs.virtualBackgroundPreferences.enabled;
|
|
}
|
|
|
|
// Apply participant permissions (these can restrict enabled features)
|
|
if (participantPerms) {
|
|
// Only restrict if the feature is already enabled
|
|
if (features.showChat) {
|
|
features.showChat = participantPerms.canChat;
|
|
}
|
|
if (features.showRecording) {
|
|
features.showRecording = participantPerms.canRecord;
|
|
}
|
|
if (features.showBackgrounds) {
|
|
features.showBackgrounds = participantPerms.canChangeVirtualBackground;
|
|
}
|
|
if (features.showScreenShare) {
|
|
features.showScreenShare = participantPerms.canPublishScreen;
|
|
}
|
|
}
|
|
|
|
if (recordingPerms) {
|
|
// Apply recording permissions
|
|
features.canDeleteRecordings = recordingPerms.canDeleteRecordings;
|
|
features.canRetrieveRecordings = recordingPerms.canRetrieveRecordings;
|
|
}
|
|
|
|
// Apply role-based configurations
|
|
if (role) {
|
|
features.canModerateRoom = role === ParticipantRole.MODERATOR;
|
|
features.canManageRecordings = role === ParticipantRole.MODERATOR;
|
|
features.canAccessConsole = role === ParticipantRole.MODERATOR;
|
|
}
|
|
|
|
this.log.d('Calculated features', features);
|
|
return features;
|
|
}
|
|
|
|
/**
|
|
* Loads initial preferences from services
|
|
*/
|
|
async initializeConfiguration(): Promise<void> {
|
|
try {
|
|
this.log.d('Initializing feature configuration');
|
|
|
|
// Load global preferences if available
|
|
// (this will depend on your GlobalPreferencesService implementation)
|
|
} catch (error) {
|
|
this.log.e('Error initializing feature configuration', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets all configurations to their initial values
|
|
*/
|
|
reset(): void {
|
|
this.globalPreferencesSubject.next(null);
|
|
this.roomPreferencesSubject.next(null);
|
|
this.participantPermissionsSubject.next(null);
|
|
this.participantRoleSubject.next(null);
|
|
}
|
|
}
|