frontend: enhance feature configuration management and update video room component to use async feature flags
This commit is contained in:
parent
acd0cb9b3d
commit
9e45716397
@ -52,17 +52,17 @@
|
|||||||
<ov-videoconference
|
<ov-videoconference
|
||||||
[token]="participantToken"
|
[token]="participantToken"
|
||||||
[participantName]="participantName"
|
[participantName]="participantName"
|
||||||
[prejoin]="featureFlags.showPrejoin"
|
[prejoin]="(features$ | async)?.showPrejoin ?? true"
|
||||||
[prejoinDisplayParticipantName]="false"
|
[prejoinDisplayParticipantName]="false"
|
||||||
[videoEnabled]="featureFlags.videoEnabled"
|
[videoEnabled]="(features$ | async)?.videoEnabled ?? true"
|
||||||
[audioEnabled]="featureFlags.audioEnabled"
|
[audioEnabled]="(features$ | async)?.audioEnabled ?? true"
|
||||||
[toolbarCameraButton]="featureFlags.showCamera"
|
[toolbarCameraButton]="(features$ | async)?.showCamera ?? true"
|
||||||
[toolbarMicrophoneButton]="featureFlags.showMicrophone"
|
[toolbarMicrophoneButton]="(features$ | async)?.showMicrophone ?? true"
|
||||||
[toolbarScreenshareButton]="featureFlags.showScreenShare"
|
[toolbarScreenshareButton]="(features$ | async)?.showScreenShare ?? true"
|
||||||
[toolbarChatPanelButton]="featureFlags.showChat"
|
[toolbarChatPanelButton]="(features$ | async)?.showChat ?? true"
|
||||||
[toolbarRecordingButton]="featureFlags.showRecording"
|
[toolbarRecordingButton]="(features$ | async)?.showRecording ?? true"
|
||||||
[toolbarBroadcastingButton]="false"
|
[toolbarBroadcastingButton]="false"
|
||||||
[toolbarBackgroundEffectsButton]="featureFlags.showBackgrounds"
|
[toolbarBackgroundEffectsButton]="(features$ | async)?.showBackgrounds ?? true"
|
||||||
[toolbarActivitiesPanelButton]="true"
|
[toolbarActivitiesPanelButton]="true"
|
||||||
[activitiesPanelRecordingActivity]="true"
|
[activitiesPanelRecordingActivity]="true"
|
||||||
[activitiesPanelBroadcastingActivity]="false"
|
[activitiesPanelBroadcastingActivity]="false"
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
|
|
||||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
@ -27,6 +29,11 @@ import {
|
|||||||
import { ParticipantTokenService } from '@lib/services/participant-token/participant-token.service';
|
import { ParticipantTokenService } from '@lib/services/participant-token/participant-token.service';
|
||||||
import { RecordingManagerService } from '@lib/services/recording-manager/recording-manager.service';
|
import { RecordingManagerService } from '@lib/services/recording-manager/recording-manager.service';
|
||||||
import { NavigationService } from '@lib/services/navigation/navigation.service';
|
import { NavigationService } from '@lib/services/navigation/navigation.service';
|
||||||
|
import {
|
||||||
|
ApplicationFeatures,
|
||||||
|
FeatureConfigurationService
|
||||||
|
} from '@lib/services/feature-configuration/feature-configuration.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-video-room',
|
selector: 'app-video-room',
|
||||||
@ -41,7 +48,8 @@ import { NavigationService } from '@lib/services/navigation/navigation.service';
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatButtonModule
|
MatButtonModule,
|
||||||
|
AsyncPipe
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class VideoRoomComponent implements OnInit, OnDestroy {
|
export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||||
@ -81,18 +89,25 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
showRecording: true,
|
showRecording: true,
|
||||||
showBackgrounds: true
|
showBackgrounds: true
|
||||||
};
|
};
|
||||||
|
features$!: Observable<ApplicationFeatures>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
protected route: ActivatedRoute,
|
||||||
protected navigationService: NavigationService,
|
protected navigationService: NavigationService,
|
||||||
protected participantTokenService: ParticipantTokenService,
|
protected participantTokenService: ParticipantTokenService,
|
||||||
protected recManagerService: RecordingManagerService,
|
protected recManagerService: RecordingManagerService,
|
||||||
protected route: ActivatedRoute,
|
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected ctxService: ContextService,
|
protected ctxService: ContextService,
|
||||||
protected roomService: RoomService,
|
protected roomService: RoomService,
|
||||||
protected wcManagerService: WebComponentManagerService,
|
protected wcManagerService: WebComponentManagerService,
|
||||||
protected sessionStorageService: SessionStorageService
|
protected sessionStorageService: SessionStorageService,
|
||||||
) {}
|
protected featureConfService: FeatureConfigurationService
|
||||||
|
) {
|
||||||
|
this.featureConfService.features$.subscribe((features) => {
|
||||||
|
console.log('!!!!!!Feature flags updated:', features);
|
||||||
|
});
|
||||||
|
this.features$ = this.featureConfService.features$;
|
||||||
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.roomId = this.ctxService.getRoomId();
|
this.roomId = this.ctxService.getRoomId();
|
||||||
@ -120,7 +135,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
try {
|
try {
|
||||||
await this.generateParticipantToken();
|
await this.generateParticipantToken();
|
||||||
await this.replaceUrlQueryParams();
|
await this.replaceUrlQueryParams();
|
||||||
await this.loadRoomPreferences();
|
await this.roomService.loadPreferences(this.roomId);
|
||||||
this.showRoom = true;
|
this.showRoom = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error accessing room:', error);
|
console.error('Error accessing room:', error);
|
||||||
@ -281,27 +296,6 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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() {
|
|
||||||
try {
|
|
||||||
this.roomPreferences = await this.roomService.getRoomPreferences();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error loading room preferences:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.featureFlags.showChat = this.roomPreferences.chatPreferences.enabled;
|
|
||||||
this.featureFlags.showRecording = this.roomPreferences.recordingPreferences.enabled;
|
|
||||||
this.featureFlags.showBackgrounds = this.roomPreferences.virtualBackgroundPreferences.enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the feature flags based on participant permissions.
|
* Configures the feature flags based on participant permissions.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -2,7 +2,13 @@ import { Injectable } from '@angular/core';
|
|||||||
import { jwtDecode } from 'jwt-decode';
|
import { jwtDecode } from 'jwt-decode';
|
||||||
import { ApplicationMode, ContextData, Edition } from '../../models/context.model';
|
import { ApplicationMode, ContextData, Edition } from '../../models/context.model';
|
||||||
import { LoggerService } from 'openvidu-components-angular';
|
import { LoggerService } from 'openvidu-components-angular';
|
||||||
import { AuthMode, HttpService, ParticipantRole } from 'projects/shared-meet-components/src/public-api';
|
import {
|
||||||
|
AuthMode,
|
||||||
|
HttpService,
|
||||||
|
OpenViduMeetPermissions,
|
||||||
|
ParticipantRole
|
||||||
|
} from 'projects/shared-meet-components/src/public-api';
|
||||||
|
import { FeatureConfigurationService } from '../feature-configuration/feature-configuration.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -36,14 +42,15 @@ export class ContextService {
|
|||||||
leaveRedirectUrl: ''
|
leaveRedirectUrl: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
private log;
|
protected log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of the ContextService class.
|
* Initializes a new instance of the ContextService class.
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private loggerService: LoggerService,
|
protected loggerService: LoggerService,
|
||||||
private httpService: HttpService
|
protected featureConfService: FeatureConfigurationService,
|
||||||
|
protected httpService: HttpService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerService.get('OpenVidu Meet - ContextService');
|
this.log = this.loggerService.get('OpenVidu Meet - ContextService');
|
||||||
}
|
}
|
||||||
@ -126,24 +133,26 @@ export class ContextService {
|
|||||||
setParticipantTokenAndUpdateContext(token: string): void {
|
setParticipantTokenAndUpdateContext(token: string): void {
|
||||||
try {
|
try {
|
||||||
const decodedToken = this.getValidDecodedToken(token);
|
const decodedToken = this.getValidDecodedToken(token);
|
||||||
this.context.participantToken = token;
|
this.setParticipantToken(token);
|
||||||
this.context.participantPermissions = decodedToken.metadata.permissions;
|
this.setParticipantPermissions(decodedToken.metadata.permissions);
|
||||||
this.context.participantRole = decodedToken.metadata.role;
|
this.setParticipantRole(decodedToken.metadata.role);
|
||||||
|
|
||||||
// Update feature configuration based on the new token
|
|
||||||
// this.updateFeatureConfiguration();
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.log.e('Error setting token in context', error);
|
this.log.e('Error setting token in context', error);
|
||||||
throw new Error('Error setting token', error);
|
throw new Error('Error setting token', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setParticipantToken(token: string): void {
|
||||||
|
this.context.participantToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
getParticipantToken(): string {
|
getParticipantToken(): string {
|
||||||
return this.context.participantToken;
|
return this.context.participantToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
setParticipantRole(participantRole: ParticipantRole): void {
|
setParticipantRole(participantRole: ParticipantRole): void {
|
||||||
this.context.participantRole = participantRole;
|
this.context.participantRole = participantRole;
|
||||||
|
this.featureConfService.setParticipantRole(participantRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
getParticipantRole(): ParticipantRole {
|
getParticipantRole(): ParticipantRole {
|
||||||
@ -154,6 +163,11 @@ export class ContextService {
|
|||||||
return this.context.participantRole === ParticipantRole.MODERATOR;
|
return this.context.participantRole === ParticipantRole.MODERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setParticipantPermissions(permissions: OpenViduMeetPermissions): void {
|
||||||
|
this.context.participantPermissions = permissions;
|
||||||
|
this.featureConfService.setParticipantPermissions(permissions);
|
||||||
|
}
|
||||||
|
|
||||||
getParticipantPermissions() {
|
getParticipantPermissions() {
|
||||||
return this.context.participantPermissions;
|
return this.context.participantPermissions;
|
||||||
}
|
}
|
||||||
@ -162,6 +176,7 @@ export class ContextService {
|
|||||||
try {
|
try {
|
||||||
const decodedToken = this.getValidDecodedToken(token);
|
const decodedToken = this.getValidDecodedToken(token);
|
||||||
this.context.recordingPermissions = decodedToken.metadata.recordingPermissions;
|
this.context.recordingPermissions = decodedToken.metadata.recordingPermissions;
|
||||||
|
this.featureConfService.setRecordingPermissions(decodedToken.metadata.recordingPermissions);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.log.e('Error setting recording token in context', error);
|
this.log.e('Error setting recording token in context', error);
|
||||||
throw new Error('Error setting recording token', error);
|
throw new Error('Error setting recording token', error);
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { FeatureConfigurationService } from './feature-configuration.service';
|
||||||
|
|
||||||
|
describe('FeatureConfigurationService', () => {
|
||||||
|
let service: FeatureConfigurationService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(FeatureConfigurationService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,249 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ import { MeetRoomPreferences } from '@lib/typings/ce';
|
|||||||
import { LoggerService } from 'openvidu-components-angular';
|
import { LoggerService } from 'openvidu-components-angular';
|
||||||
import { HttpService } from '../http/http.service';
|
import { HttpService } from '../http/http.service';
|
||||||
import { MeetRoom, MeetRoomOptions } from 'projects/shared-meet-components/src/lib/typings/ce/room';
|
import { MeetRoom, MeetRoomOptions } from 'projects/shared-meet-components/src/lib/typings/ce/room';
|
||||||
|
import { FeatureConfigurationService } from '../feature-configuration/feature-configuration.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -12,7 +13,8 @@ export class RoomService {
|
|||||||
protected roomPreferences: MeetRoomPreferences | undefined;
|
protected roomPreferences: MeetRoomPreferences | undefined;
|
||||||
constructor(
|
constructor(
|
||||||
protected loggerService: LoggerService,
|
protected loggerService: LoggerService,
|
||||||
protected httpService: HttpService
|
protected httpService: HttpService,
|
||||||
|
protected featureConfService: FeatureConfigurationService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerService.get('OpenVidu Meet - RoomService');
|
this.log = this.loggerService.get('OpenVidu Meet - RoomService');
|
||||||
}
|
}
|
||||||
@ -39,14 +41,23 @@ export class RoomService {
|
|||||||
return this.httpService.getRoom(roomId);
|
return this.httpService.getRoom(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRoomPreferences(): Promise<MeetRoomPreferences> {
|
async loadPreferences(roomId: string, forceUpdate: boolean = false): Promise<MeetRoomPreferences> {
|
||||||
if (!this.roomPreferences) {
|
if (this.roomPreferences && !forceUpdate) {
|
||||||
this.log.d('Room preferences not found, fetching from server');
|
this.log.d('Returning cached room preferences');
|
||||||
// Fetch the room preferences from the server
|
return this.roomPreferences;
|
||||||
this.roomPreferences = await this.httpService.getRoomPreferences();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.roomPreferences;
|
this.log.d('Fetching room preferences from server');
|
||||||
|
try {
|
||||||
|
const room = await this.getRoom(roomId);
|
||||||
|
this.roomPreferences = room.preferences! as MeetRoomPreferences;
|
||||||
|
this.featureConfService.setRoomPreferences(this.roomPreferences);
|
||||||
|
console.log('Room preferences loaded:', this.roomPreferences);
|
||||||
|
return this.roomPreferences;
|
||||||
|
} catch (error) {
|
||||||
|
this.log.e('Error loading room preferences', error);
|
||||||
|
throw new Error('Failed to load room preferences');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user