mirror of https://github.com/OpenVidu/openvidu.git
ov-components: Refactor prejoin logic and improve observable handling in configuration service
parent
bcbf24b84d
commit
1762c43769
|
@ -10,7 +10,7 @@ import {
|
|||
Output
|
||||
} from '@angular/core';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { filter, Subject, takeUntil, tap } from 'rxjs';
|
||||
import { filter, Subject, take, takeUntil, tap } from 'rxjs';
|
||||
import { ILogger } from '../../models/logger.model';
|
||||
import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service';
|
||||
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
|
||||
|
@ -175,15 +175,12 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
if (this.participantName?.trim()) {
|
||||
this.libService.updateGeneralConfig({ participantName: this.participantName.trim() });
|
||||
|
||||
// Wait for the next tick to ensure the participant name propagates
|
||||
// through the observable before emitting onReadyToJoin
|
||||
this.libService.participantName$
|
||||
.pipe(
|
||||
takeUntil(this.destroy$),
|
||||
filter((name) => name === this.participantName?.trim()),
|
||||
tap(() => this.onReadyToJoin.emit())
|
||||
take(1)
|
||||
)
|
||||
.subscribe();
|
||||
.subscribe(() => this.onReadyToJoin.emit());
|
||||
} else {
|
||||
// No participant name to set, emit immediately
|
||||
this.onReadyToJoin.emit();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[(ngModel)]="name"
|
||||
autocomplete="off"
|
||||
[disabled]="!isPrejoinPage"
|
||||
(change)="updateName()"
|
||||
(input)="updateName()"
|
||||
(keypress)="eventKeyPress($event)"
|
||||
[placeholder]="'PREJOIN.NICKNAME' | translate"
|
||||
class="name-input-field"
|
||||
|
|
|
@ -836,7 +836,6 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit {
|
|||
*/
|
||||
_onReadyToJoin(): void {
|
||||
this.log.d('Ready to join - initializing room and handling prejoin flow');
|
||||
|
||||
try {
|
||||
// Mark that user has initiated the join process
|
||||
this.updateComponentState({
|
||||
|
@ -921,15 +920,7 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit {
|
|||
this.openviduService.initializeAndSetToken(token, livekitUrl);
|
||||
this.log.d('Token has been successfully set. Room is ready to join');
|
||||
|
||||
// Only update showPrejoin if user hasn't initiated join process yet
|
||||
// This prevents prejoin from showing again after user clicked join
|
||||
if (!this.hasUserInitiatedJoin()) {
|
||||
this.updateComponentState({
|
||||
state: VideoconferenceState.PREJOIN_SHOWN,
|
||||
isRoomReady: true,
|
||||
showPrejoin: this.libService.showPrejoin()
|
||||
});
|
||||
} else {
|
||||
if (this.hasUserInitiatedJoin()) {
|
||||
// User has initiated join, proceed to hide prejoin and continue
|
||||
this.log.d('User has initiated join, hiding prejoin and proceeding');
|
||||
this.updateComponentState({
|
||||
|
@ -937,6 +928,21 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit {
|
|||
isRoomReady: true,
|
||||
showPrejoin: false
|
||||
});
|
||||
console.log(this.componentState);
|
||||
console.warn(
|
||||
this.componentState.isRoomReady &&
|
||||
!this.componentState.showPrejoin &&
|
||||
!this.componentState.isLoading &&
|
||||
!this.componentState.error?.hasError
|
||||
);
|
||||
} else {
|
||||
// Only update showPrejoin if user hasn't initiated join process yet
|
||||
// This prevents prejoin from showing again after user clicked join
|
||||
this.updateComponentState({
|
||||
state: VideoconferenceState.PREJOIN_SHOWN,
|
||||
isRoomReady: true,
|
||||
showPrejoin: this.libService.showPrejoin()
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.log.e('Error trying to set token', error);
|
||||
|
|
|
@ -199,10 +199,7 @@ export class OpenViduComponentsConfigService {
|
|||
*/
|
||||
private createGeneralConfigItem(initialValue: GeneralConfig): ConfigItem<GeneralConfig> {
|
||||
const subject = new BehaviorSubject<GeneralConfig>(initialValue);
|
||||
const observable$ = subject.asObservable().pipe(
|
||||
distinctUntilChanged((prev, curr) => this.compareGeneralConfig(prev, curr)),
|
||||
shareReplay(1)
|
||||
);
|
||||
const observable$ = subject.asObservable();
|
||||
return { subject, observable$ };
|
||||
}
|
||||
|
||||
|
@ -297,7 +294,7 @@ export class OpenViduComponentsConfigService {
|
|||
* Compare GeneralConfig efficiently
|
||||
*/
|
||||
private compareGeneralConfig(prev: GeneralConfig, curr: GeneralConfig): boolean {
|
||||
return (
|
||||
const equal =
|
||||
prev.token === curr.token &&
|
||||
prev.livekitUrl === curr.livekitUrl &&
|
||||
prev.tokenError === curr.tokenError &&
|
||||
|
@ -306,8 +303,12 @@ export class OpenViduComponentsConfigService {
|
|||
prev.prejoin === curr.prejoin &&
|
||||
prev.prejoinDisplayParticipantName === curr.prejoinDisplayParticipantName &&
|
||||
prev.showDisconnectionDialog === curr.showDisconnectionDialog &&
|
||||
prev.recordingStreamBaseUrl === curr.recordingStreamBaseUrl
|
||||
);
|
||||
prev.recordingStreamBaseUrl === curr.recordingStreamBaseUrl;
|
||||
|
||||
if (!equal) {
|
||||
console.log('GeneralConfig cambió', { prev, curr });
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
// Grouped configuration items by domain
|
||||
|
@ -380,17 +381,51 @@ export class OpenViduComponentsConfigService {
|
|||
private layoutRemoteParticipantsConfig = this.createConfigItem<ParticipantModel[] | undefined>(undefined);
|
||||
|
||||
// General observables
|
||||
token$: Observable<string> = this.generalConfig.observable$.pipe(map((config) => config.token));
|
||||
livekitUrl$: Observable<string> = this.generalConfig.observable$.pipe(map((config) => config.livekitUrl));
|
||||
tokenError$: Observable<any> = this.generalConfig.observable$.pipe(map((config) => config.tokenError));
|
||||
minimal$: Observable<boolean> = this.generalConfig.observable$.pipe(map((config) => config.minimal));
|
||||
participantName$: Observable<string> = this.generalConfig.observable$.pipe(map((config) => config.participantName));
|
||||
prejoin$: Observable<boolean> = this.generalConfig.observable$.pipe(map((config) => config.prejoin));
|
||||
prejoinDisplayParticipantName$: Observable<boolean> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.prejoinDisplayParticipantName)
|
||||
token$: Observable<string> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.token),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
livekitUrl$: Observable<string> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.livekitUrl),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
tokenError$: Observable<any> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.tokenError),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
minimal$: Observable<boolean> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.minimal),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
participantName$: Observable<string> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.participantName),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
prejoin$: Observable<boolean> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.prejoin),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
prejoinDisplayParticipantName$: Observable<boolean> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.prejoinDisplayParticipantName),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
showDisconnectionDialog$: Observable<boolean> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.showDisconnectionDialog),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
recordingStreamBaseUrl$: Observable<string> = this.generalConfig.observable$.pipe(
|
||||
map((config) => config.recordingStreamBaseUrl),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
);
|
||||
showDisconnectionDialog$: Observable<boolean> = this.generalConfig.observable$.pipe(map((config) => config.showDisconnectionDialog));
|
||||
recordingStreamBaseUrl$: Observable<string> = this.generalConfig.observable$.pipe(map((config) => config.recordingStreamBaseUrl));
|
||||
|
||||
// Stream observables
|
||||
videoEnabled$: Observable<boolean> = this.streamConfig.observable$.pipe(map((config) => config.videoEnabled));
|
||||
|
|
|
@ -177,16 +177,20 @@ export class OpenViduService {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
initializeAndSetToken(token: string, livekitUrl: string): void {
|
||||
const livekitData = this.extractLivekitData(token, livekitUrl);
|
||||
this.livekitToken = token;
|
||||
this.livekitUrl = livekitData.livekitUrl;
|
||||
initializeAndSetToken(token: string, livekitUrl?: string): void {
|
||||
const { livekitUrl: urlFromToken } = this.extractLivekitData(token);
|
||||
|
||||
if (!this.livekitUrl) {
|
||||
this.livekitToken = token;
|
||||
const url = livekitUrl || urlFromToken;
|
||||
|
||||
if (!url) {
|
||||
this.log.e('LiveKit URL is not defined. Please, check the livekitUrl parameter of the VideoConferenceComponent');
|
||||
throw new Error('Livekit URL is not defined');
|
||||
}
|
||||
|
||||
this.livekitUrl = url;
|
||||
// this.livekitRoomAdmin = !!livekitRoomAdmin;
|
||||
|
||||
// Initialize room if it doesn't exist yet
|
||||
// This ensures that getRoom() won't fail if token is set before onTokenRequested
|
||||
if (!this.room) {
|
||||
|
@ -370,9 +374,8 @@ export class OpenViduService {
|
|||
* @throws Error if there is an error decoding and parsing the token.
|
||||
* @internal
|
||||
*/
|
||||
private extractLivekitData(token: string, livekitUrl: string): { livekitUrl: string; livekitRoomAdmin: boolean } {
|
||||
private extractLivekitData(token: string): { livekitUrl?: string; livekitRoomAdmin: boolean } {
|
||||
try {
|
||||
const response = { livekitUrl, livekitRoomAdmin: false };
|
||||
const base64Url = token.split('.')[1];
|
||||
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
||||
const jsonPayload = decodeURIComponent(
|
||||
|
@ -388,13 +391,13 @@ export class OpenViduService {
|
|||
const payload = JSON.parse(jsonPayload);
|
||||
if (payload?.metadata) {
|
||||
const tokenMetadata = JSON.parse(payload.metadata);
|
||||
if (tokenMetadata.livekitUrl) {
|
||||
response.livekitUrl = tokenMetadata.livekitUrl;
|
||||
}
|
||||
response.livekitRoomAdmin = tokenMetadata.roomAdmin;
|
||||
return {
|
||||
livekitUrl: tokenMetadata.livekitUrl,
|
||||
livekitRoomAdmin: !!tokenMetadata.roomAdmin
|
||||
};
|
||||
}
|
||||
|
||||
return response;
|
||||
return { livekitRoomAdmin: false };
|
||||
} catch (error) {
|
||||
throw new Error('Error decoding and parsing token: ' + error);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue