frontend: rename RoomMemberContextService references and implement RoomMemberContextAdapter for improved context management
This commit is contained in:
parent
7cdfdf20f9
commit
e45aa91d90
@ -33,7 +33,7 @@ export const validateRoomRecordingsAccessGuard: CanActivateFn = async (
|
||||
* @returns True if access is granted, or UrlTree for redirection
|
||||
*/
|
||||
const validateRoomAccessInternal = async (pageUrl: string, validateRecordingPermissions = false) => {
|
||||
const roomMemberService = inject(RoomMemberContextService);
|
||||
const roomMemberContextService = inject(RoomMemberContextService);
|
||||
const navigationService = inject(NavigationService);
|
||||
const meetingContextService = inject(MeetingContextService);
|
||||
|
||||
@ -45,14 +45,14 @@ const validateRoomAccessInternal = async (pageUrl: string, validateRecordingPerm
|
||||
}
|
||||
|
||||
try {
|
||||
await roomMemberService.generateToken(roomId, {
|
||||
await roomMemberContextService.generateToken(roomId, {
|
||||
secret,
|
||||
joinMeeting: false
|
||||
});
|
||||
|
||||
// Perform recording validation if requested
|
||||
if (validateRecordingPermissions) {
|
||||
if (!roomMemberService.hasPermission('canRetrieveRecordings')) {
|
||||
if (!roomMemberContextService.hasPermission('canRetrieveRecordings')) {
|
||||
// If the user does not have permission to retrieve recordings, redirect to the error page
|
||||
return navigationService.redirectToErrorPage(NavigationErrorReason.FORBIDDEN_RECORDING_ACCESS);
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ export class MeetingComponent implements OnInit {
|
||||
protected isMeetingLeft = signal(false);
|
||||
|
||||
protected features: Signal<RoomFeatures>;
|
||||
protected participantService = inject(RoomMemberContextService);
|
||||
protected roomMemberContextService = inject(RoomMemberContextService);
|
||||
protected roomFeatureService = inject(RoomFeatureService);
|
||||
protected ovThemeService = inject(OpenViduThemeService);
|
||||
protected configService = inject(GlobalConfigService);
|
||||
|
||||
@ -40,7 +40,7 @@ export class MeetingEventHandlerService {
|
||||
protected meetingContext = inject(MeetingContextService);
|
||||
protected roomFeatureService = inject(RoomFeatureService);
|
||||
protected recordingService = inject(RecordingService);
|
||||
protected roomMemberService = inject(RoomMemberContextService);
|
||||
protected roomMemberContextService = inject(RoomMemberContextService);
|
||||
protected sessionStorageService = inject(SessionStorageService);
|
||||
protected tokenStorageService = inject(TokenStorageService);
|
||||
protected wcManagerService = inject(MeetingWebComponentManagerService);
|
||||
@ -158,8 +158,7 @@ export class MeetingEventHandlerService {
|
||||
this.wcManagerService.sendMessageToParent(message);
|
||||
|
||||
// Clear participant identity and token
|
||||
this.roomMemberService.clearParticipantIdentity();
|
||||
this.tokenStorageService.clearRoomMemberToken();
|
||||
this.roomMemberContextService.clearContext();
|
||||
|
||||
// Clean up room secret and e2ee key (if any), except on browser unload)
|
||||
if (event.reason !== ParticipantLeftReason.BROWSER_UNLOAD) {
|
||||
@ -257,7 +256,7 @@ export class MeetingEventHandlerService {
|
||||
const { participantIdentity, newRole, secret } = event;
|
||||
const roomId = this.meetingContext.roomId();
|
||||
const local = this.meetingContext.localParticipant();
|
||||
const participantName = this.roomMemberService.getParticipantName();
|
||||
const participantName = this.roomMemberContextService.getParticipantName();
|
||||
|
||||
// Check if the role update is for the local participant
|
||||
if (local && participantIdentity === local.identity) {
|
||||
@ -269,7 +268,7 @@ export class MeetingEventHandlerService {
|
||||
|
||||
try {
|
||||
// Refresh participant token with new role
|
||||
await this.roomMemberService.generateToken(roomId, {
|
||||
await this.roomMemberContextService.generateToken(roomId, {
|
||||
secret,
|
||||
joinMeeting: true,
|
||||
participantName,
|
||||
|
||||
@ -46,7 +46,7 @@ export class MeetingLobbyService {
|
||||
protected meetingService: MeetingService = inject(MeetingService);
|
||||
protected recordingService: RecordingService = inject(RecordingService);
|
||||
protected authService: AuthService = inject(AuthService);
|
||||
protected roomMemberService: RoomMemberContextService = inject(RoomMemberContextService);
|
||||
protected roomMemberContextService: RoomMemberContextService = inject(RoomMemberContextService);
|
||||
protected navigationService: NavigationService = inject(NavigationService);
|
||||
protected appCtxService: AppContextService = inject(AppContextService);
|
||||
protected wcManagerService: MeetingWebComponentManagerService = inject(MeetingWebComponentManagerService);
|
||||
@ -290,7 +290,7 @@ export class MeetingLobbyService {
|
||||
*/
|
||||
protected async checkForRecordings(): Promise<void> {
|
||||
try {
|
||||
const canRetrieveRecordings = this.roomMemberService.hasPermission('canRetrieveRecordings');
|
||||
const canRetrieveRecordings = this.roomMemberContextService.hasPermission('canRetrieveRecordings');
|
||||
|
||||
if (!canRetrieveRecordings) {
|
||||
this._state.update((state) => ({ ...state, showRecordingCard: false }));
|
||||
@ -332,7 +332,7 @@ export class MeetingLobbyService {
|
||||
*/
|
||||
protected async initializeParticipantName(): Promise<void> {
|
||||
// Apply participant name from RoomMemberService if set, otherwise use authenticated username
|
||||
const currentParticipantName = this.roomMemberService.getParticipantName();
|
||||
const currentParticipantName = this.roomMemberContextService.getParticipantName();
|
||||
const username = await this.authService.getUserName();
|
||||
const participantName = currentParticipantName || username;
|
||||
|
||||
@ -350,7 +350,7 @@ export class MeetingLobbyService {
|
||||
try {
|
||||
const roomId = this._state().roomId;
|
||||
const roomSecret = this.meetingContextService.roomSecret();
|
||||
const roomMemberToken = await this.roomMemberService.generateToken(
|
||||
const roomMemberToken = await this.roomMemberContextService.generateToken(
|
||||
roomId!,
|
||||
{
|
||||
secret: roomSecret,
|
||||
@ -359,7 +359,7 @@ export class MeetingLobbyService {
|
||||
},
|
||||
this.e2eeKeyValue()
|
||||
);
|
||||
const updatedName = this.roomMemberService.getParticipantName()!;
|
||||
const updatedName = this.roomMemberContextService.getParticipantName()!;
|
||||
this.setParticipantName(updatedName);
|
||||
this._state.update((state) => ({ ...state, roomMemberToken }));
|
||||
} catch (error: any) {
|
||||
|
||||
@ -26,7 +26,7 @@ export class MeetingWebComponentManagerService {
|
||||
|
||||
protected log;
|
||||
protected readonly meetingContextService = inject(MeetingContextService);
|
||||
protected readonly roomMemberService = inject(RoomMemberContextService);
|
||||
protected readonly roomMemberContextService = inject(RoomMemberContextService);
|
||||
protected readonly openviduService = inject(OpenViduService);
|
||||
protected readonly meetingService = inject(MeetingService);
|
||||
protected readonly loggerService = inject(LoggerService);
|
||||
@ -122,7 +122,7 @@ export class MeetingWebComponentManagerService {
|
||||
switch (command) {
|
||||
case WebComponentCommand.END_MEETING:
|
||||
// Only participants with canEndMeeting permission can end the meeting
|
||||
if (!this.roomMemberService.hasPermission('canEndMeeting')) {
|
||||
if (!this.roomMemberContextService.hasPermission('canEndMeeting')) {
|
||||
this.log.w(
|
||||
'End meeting command received but participant does not have permissions to end the meeting'
|
||||
);
|
||||
@ -144,7 +144,7 @@ export class MeetingWebComponentManagerService {
|
||||
break;
|
||||
case WebComponentCommand.KICK_PARTICIPANT:
|
||||
// Only participants with canKickParticipants permission can kick participants
|
||||
if (!this.roomMemberService.hasPermission('canKickParticipants')) {
|
||||
if (!this.roomMemberContextService.hasPermission('canKickParticipants')) {
|
||||
this.log.w(
|
||||
'Kick participant command received but participant does not have permissions to kick participants'
|
||||
);
|
||||
|
||||
@ -46,7 +46,7 @@ export class RoomRecordingsComponent implements OnInit {
|
||||
|
||||
protected readonly loggerService = inject(LoggerService);
|
||||
protected readonly recordingService = inject(RecordingService);
|
||||
protected readonly roomMemberService = inject(RoomMemberContextService);
|
||||
protected readonly roomMemberContextService = inject(RoomMemberContextService);
|
||||
protected readonly notificationService = inject(NotificationService);
|
||||
protected readonly navigationService = inject(NavigationService);
|
||||
protected readonly meetingContextService = inject(MeetingContextService);
|
||||
@ -58,7 +58,7 @@ export class RoomRecordingsComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this.roomId = this.route.snapshot.paramMap.get('room-id')!;
|
||||
this.canDeleteRecordings = this.roomMemberService.hasPermission('canDeleteRecordings');
|
||||
this.canDeleteRecordings = this.roomMemberContextService.hasPermission('canDeleteRecordings');
|
||||
|
||||
// Load recordings
|
||||
const delayLoader = setTimeout(() => {
|
||||
|
||||
@ -4,6 +4,7 @@ import { MeetRecordingFilters, MeetRecordingInfo } from '@openvidu-meet/typings'
|
||||
import { LoggerService } from 'openvidu-components-angular';
|
||||
import { HttpService } from '../../../shared/services/http.service';
|
||||
import { TokenStorageService } from '../../../shared/services/token-storage.service';
|
||||
import { RoomMemberContextService } from '../../room-members/services/room-member-context.service';
|
||||
import { RecordingShareDialogComponent } from '../components/recording-share-dialog/recording-share-dialog.component';
|
||||
|
||||
@Injectable({
|
||||
@ -19,6 +20,7 @@ export class RecordingService {
|
||||
protected loggerService: LoggerService,
|
||||
private httpService: HttpService,
|
||||
protected tokenStorageService: TokenStorageService,
|
||||
protected roomMemberContextService: RoomMemberContextService,
|
||||
protected dialog: MatDialog
|
||||
) {
|
||||
this.log = this.loggerService.get('OpenVidu Meet - RecordingManagerService');
|
||||
@ -130,7 +132,7 @@ export class RecordingService {
|
||||
params.append('accessToken', accessToken);
|
||||
}
|
||||
|
||||
const roomMemberToken = this.tokenStorageService.getRoomMemberToken();
|
||||
const roomMemberToken = this.roomMemberContextService.getRoomMemberToken();
|
||||
if (roomMemberToken) {
|
||||
params.append('roomMemberToken', roomMemberToken);
|
||||
}
|
||||
@ -226,7 +228,7 @@ export class RecordingService {
|
||||
params.append('accessToken', accessToken);
|
||||
}
|
||||
|
||||
const roomMemberToken = this.tokenStorageService.getRoomMemberToken();
|
||||
const roomMemberToken = this.roomMemberContextService.getRoomMemberToken();
|
||||
if (roomMemberToken) {
|
||||
params.append('roomMemberToken', roomMemberToken);
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './interceptor-handlers';
|
||||
export * from './providers';
|
||||
export * from './services';
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
HttpErrorHandler,
|
||||
HttpErrorNotifierService
|
||||
} from '../../../shared/services/http-error-notifier.service';
|
||||
import { TokenStorageService } from '../../../shared/services/token-storage.service';
|
||||
import { MeetingContextService } from '../../meeting/services/meeting-context.service';
|
||||
import { RoomMemberContextService } from '../services/room-member-context.service';
|
||||
|
||||
@ -19,9 +18,8 @@ import { RoomMemberContextService } from '../services/room-member-context.servic
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandler {
|
||||
private readonly roomMemberService = inject(RoomMemberContextService);
|
||||
private readonly roomMemberContextService = inject(RoomMemberContextService);
|
||||
private readonly meetingContextService = inject(MeetingContextService);
|
||||
private readonly tokenStorageService = inject(TokenStorageService);
|
||||
private readonly httpErrorNotifier = inject(HttpErrorNotifierService);
|
||||
|
||||
/**
|
||||
@ -77,12 +75,12 @@ export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandle
|
||||
return throwError(() => originalError);
|
||||
}
|
||||
|
||||
const participantName = this.roomMemberService.getParticipantName();
|
||||
const participantIdentity = this.roomMemberService.getParticipantIdentity();
|
||||
const participantName = this.roomMemberContextService.getParticipantName();
|
||||
const participantIdentity = this.roomMemberContextService.getParticipantIdentity();
|
||||
const joinMeeting = !!participantIdentity; // Grant join permission if identity is set
|
||||
|
||||
return from(
|
||||
this.roomMemberService.generateToken(roomId, {
|
||||
this.roomMemberContextService.generateToken(roomId, {
|
||||
secret,
|
||||
joinMeeting,
|
||||
participantName,
|
||||
@ -92,7 +90,7 @@ export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandle
|
||||
switchMap(() => {
|
||||
console.log('Room member token refreshed');
|
||||
// Update the request with the new token
|
||||
const newToken = this.tokenStorageService.getRoomMemberToken();
|
||||
const newToken = this.roomMemberContextService.getRoomMemberToken();
|
||||
const updatedRequest = newToken
|
||||
? originalRequest.clone({
|
||||
setHeaders: {
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export * from './room-member-context.provider';
|
||||
@ -0,0 +1,12 @@
|
||||
import { Provider } from '@angular/core';
|
||||
import { ROOM_MEMBER_CONTEXT_ADAPTER } from '../../../shared/adapters/room-member-context.adapter';
|
||||
import { RoomMemberContextService } from '../services/room-member-context.service';
|
||||
|
||||
/**
|
||||
* Provides the RoomMemberContextAdapter using the existing RoomMemberContextService.
|
||||
* This allows shared guards to use the adapter interface without depending on domain services.
|
||||
*/
|
||||
export const ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER: Provider = {
|
||||
provide: ROOM_MEMBER_CONTEXT_ADAPTER,
|
||||
useExisting: RoomMemberContextService
|
||||
};
|
||||
@ -1,7 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
MeetRoomMemberPermissions,
|
||||
MeetRoomMemberRole,
|
||||
MeetRoomMemberTokenMetadata,
|
||||
MeetRoomMemberTokenOptions
|
||||
} from '@openvidu-meet/typings';
|
||||
@ -17,9 +16,9 @@ import { RoomMemberService } from './room-member.service';
|
||||
export class RoomMemberContextService {
|
||||
protected readonly PARTICIPANT_NAME_KEY = 'ovMeet-participantName';
|
||||
|
||||
protected roomMemberToken?: string;
|
||||
protected participantName?: string;
|
||||
protected participantIdentity?: string;
|
||||
protected role: MeetRoomMemberRole = MeetRoomMemberRole.SPEAKER;
|
||||
protected permissions?: MeetRoomMemberPermissions;
|
||||
|
||||
protected log;
|
||||
@ -34,6 +33,15 @@ export class RoomMemberContextService {
|
||||
this.log = this.loggerService.get('OpenVidu Meet - RoomMemberContextService');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current room member token.
|
||||
*
|
||||
* @returns The room member token, or undefined if not set
|
||||
*/
|
||||
getRoomMemberToken(): string | undefined {
|
||||
return this.roomMemberToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the participant's display name and stores it in localStorage.
|
||||
*
|
||||
@ -62,13 +70,6 @@ export class RoomMemberContextService {
|
||||
return this.participantIdentity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the participant's identity.
|
||||
*/
|
||||
clearParticipantIdentity(): void {
|
||||
this.participantIdentity = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current room member has a specific permission.
|
||||
*
|
||||
@ -96,13 +97,13 @@ export class RoomMemberContextService {
|
||||
}
|
||||
|
||||
const { token } = await this.roomMemberService.generateRoomMemberToken(roomId, tokenOptions);
|
||||
this.tokenStorageService.setRoomMemberToken(token);
|
||||
this.roomMemberToken = token;
|
||||
await this.updateContextFromToken(token);
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the room member context (role and permissions) based on the provided token.
|
||||
* Updates the room member context based on the provided token.
|
||||
*
|
||||
* @param token - The room member token
|
||||
* @throws Error if the token is invalid or expired.
|
||||
@ -118,15 +119,24 @@ export class RoomMemberContextService {
|
||||
this.participantIdentity = decodedToken.sub;
|
||||
}
|
||||
|
||||
this.role = metadata.baseRole;
|
||||
this.permissions = metadata.effectivePermissions;
|
||||
|
||||
// Update feature configuration
|
||||
this.roomFeatureService.setRoomMemberRole(this.role);
|
||||
this.roomFeatureService.setRoomMemberRole(metadata.baseRole);
|
||||
this.roomFeatureService.setRoomMemberPermissions(this.permissions);
|
||||
} catch (error) {
|
||||
this.log.e('Error decoding room member token:', error);
|
||||
throw new Error('Invalid room member token');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the room member context, including token, participant info, role, and permissions.
|
||||
*/
|
||||
clearContext(): void {
|
||||
this.roomMemberToken = undefined;
|
||||
this.participantName = undefined;
|
||||
this.participantIdentity = undefined;
|
||||
this.permissions = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export * from './room-member-context.adapter';
|
||||
@ -0,0 +1,17 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Adapter interface for room member context, providing necessary methods to access room member information.
|
||||
* This allows shared services to interact with room member context without directly depending on domain services.
|
||||
*/
|
||||
export interface RoomMemberContextAdapter {
|
||||
/**
|
||||
* Retrieves the current room member token.
|
||||
*/
|
||||
getRoomMemberToken(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection token for the RoomMemberContextAdapter
|
||||
*/
|
||||
export const ROOM_MEMBER_CONTEXT_ADAPTER = new InjectionToken<RoomMemberContextAdapter>('ROOM_MEMBER_CONTEXT_ADAPTER');
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './adapters';
|
||||
export * from './components';
|
||||
export * from './guards';
|
||||
export * from './interceptors';
|
||||
|
||||
@ -2,6 +2,7 @@ import { HttpErrorResponse, HttpHandlerFn, HttpInterceptorFn, HttpRequest } from
|
||||
import { inject } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { catchError, throwError } from 'rxjs';
|
||||
import { ROOM_MEMBER_CONTEXT_ADAPTER, RoomMemberContextAdapter } from '../adapters';
|
||||
import { HttpErrorNotifierService, TokenStorageService } from '../services';
|
||||
|
||||
/**
|
||||
@ -11,7 +12,8 @@ import { HttpErrorNotifierService, TokenStorageService } from '../services';
|
||||
*/
|
||||
const addAuthHeadersIfNeeded = (
|
||||
req: HttpRequest<unknown>,
|
||||
tokenStorageService: TokenStorageService
|
||||
tokenStorageService: TokenStorageService,
|
||||
roomMemberContextService: RoomMemberContextAdapter
|
||||
): HttpRequest<unknown> => {
|
||||
const headers: { [key: string]: string } = {};
|
||||
|
||||
@ -22,7 +24,7 @@ const addAuthHeadersIfNeeded = (
|
||||
}
|
||||
|
||||
// Add room member token header if available
|
||||
const roomMemberToken = tokenStorageService.getRoomMemberToken();
|
||||
const roomMemberToken = roomMemberContextService.getRoomMemberToken();
|
||||
if (roomMemberToken) {
|
||||
headers['x-room-member-token'] = `Bearer ${roomMemberToken}`;
|
||||
}
|
||||
@ -42,12 +44,13 @@ const addAuthHeadersIfNeeded = (
|
||||
export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
|
||||
const router = inject(Router);
|
||||
const tokenStorageService = inject(TokenStorageService);
|
||||
const roomMemberContextService = inject(ROOM_MEMBER_CONTEXT_ADAPTER);
|
||||
const httpErrorNotifier = inject(HttpErrorNotifierService);
|
||||
|
||||
const pageUrl = router.currentNavigation()?.finalUrl?.toString() || router.url;
|
||||
|
||||
// Add all authorization headers if tokens exist
|
||||
req = addAuthHeadersIfNeeded(req, tokenStorageService);
|
||||
req = addAuthHeadersIfNeeded(req, tokenStorageService, roomMemberContextService);
|
||||
|
||||
return next(req).pipe(
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Service to manage JWT token storage when using header-based authentication.
|
||||
* Tokens are stored in localStorage/sessionStorage when authTransportMode is 'header'.
|
||||
* Service to manage JWT token storage for authentication
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -10,9 +9,6 @@ import { Injectable } from '@angular/core';
|
||||
export class TokenStorageService {
|
||||
private readonly ACCESS_TOKEN_KEY = 'ovMeet-accessToken';
|
||||
private readonly REFRESH_TOKEN_KEY = 'ovMeet-refreshToken';
|
||||
private readonly ROOM_MEMBER_TOKEN_KEY = 'ovMeet-roomMemberToken';
|
||||
|
||||
// ACCESS AND REFRESH TOKEN METHODS
|
||||
|
||||
// Saves the access token to localStorage
|
||||
setAccessToken(token: string): void {
|
||||
@ -39,22 +35,4 @@ export class TokenStorageService {
|
||||
localStorage.removeItem(this.ACCESS_TOKEN_KEY);
|
||||
localStorage.removeItem(this.REFRESH_TOKEN_KEY);
|
||||
}
|
||||
|
||||
// ROOM MEMBER TOKEN METHODS
|
||||
// Uses sessionStorage instead of localStorage to ensure token is not shared across browser tabs
|
||||
|
||||
// Saves the room member token to sessionStorage
|
||||
setRoomMemberToken(token: string): void {
|
||||
sessionStorage.setItem(this.ROOM_MEMBER_TOKEN_KEY, token);
|
||||
}
|
||||
|
||||
// Retrieves the room member token from sessionStorage
|
||||
getRoomMemberToken(): string | null {
|
||||
return sessionStorage.getItem(this.ROOM_MEMBER_TOKEN_KEY);
|
||||
}
|
||||
|
||||
// Removes the room member token from sessionStorage
|
||||
clearRoomMemberToken(): void {
|
||||
sessionStorage.removeItem(this.ROOM_MEMBER_TOKEN_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
CustomParticipantModel,
|
||||
httpInterceptor,
|
||||
MeetingLayoutService,
|
||||
ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER,
|
||||
RoomMemberInterceptorErrorHandlerService,
|
||||
ThemeService
|
||||
} from '@openvidu-meet/shared-components';
|
||||
@ -38,6 +39,7 @@ export const appConfig: ApplicationConfig = {
|
||||
provideAppInitializer(() => inject(RoomMemberInterceptorErrorHandlerService).init()),
|
||||
importProvidersFrom(OpenViduComponentsModule.forRoot(ovComponentsconfig)),
|
||||
{ provide: LayoutService, useClass: MeetingLayoutService },
|
||||
ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER,
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(ceRoutes),
|
||||
provideAnimationsAsync(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user