diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/layout/layout.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/layout/layout.component.ts index 3e7655d5..1d345b36 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/layout/layout.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/layout/layout.component.ts @@ -11,7 +11,7 @@ import { ViewChild, ViewContainerRef } from '@angular/core'; -import { combineLatest, map, Subscription } from 'rxjs'; +import { combineLatest, map, Subject, takeUntil } from 'rxjs'; import { StreamDirective } from '../../directives/template/openvidu-components-angular.directive'; import { ParticipantTrackPublication, ParticipantModel } from '../../models/participant.model'; import { LayoutService } from '../../services/layout/layout.service'; @@ -72,11 +72,8 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { */ captionsEnabled = true; - private localParticipantSubs: Subscription; - private remoteParticipantsSubs: Subscription; - private captionsSubs: Subscription; + private destroy$ = new Subject(); private resizeObserver: ResizeObserver; - private cdkSubscription: Subscription; private resizeTimeout: NodeJS.Timeout; private videoIsAtRight: boolean = false; private lastLayoutWidth: number = 0; @@ -107,13 +104,11 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { } ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); this.localParticipant = undefined; this.remoteParticipants = []; this.resizeObserver?.disconnect(); - this.localParticipantSubs?.unsubscribe(); - this.remoteParticipantsSubs?.unsubscribe(); - this.captionsSubs?.unsubscribe(); - this.cdkSubscription?.unsubscribe(); this.layoutService.clear(); } @@ -127,33 +122,38 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToCaptions() { - this.captionsSubs = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => { - this.captionsEnabled = value; - this.cd.markForCheck(); - this.layoutService.update(); - }); + this.layoutService.captionsTogglingObs + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.captionsEnabled = value; + this.cd.markForCheck(); + this.layoutService.update(); + }); } private subscribeToParticipants() { - this.localParticipantSubs = this.participantService.localParticipant$.subscribe((p) => { - if (p) { - this.localParticipant = p; - if (!this.localParticipant?.isMinimized) { - this.videoIsAtRight = false; + this.participantService.localParticipant$ + .pipe(takeUntil(this.destroy$)) + .subscribe((p) => { + if (p) { + this.localParticipant = p; + if (!this.localParticipant?.isMinimized) { + this.videoIsAtRight = false; + } + this.layoutService.update(); + this.cd.markForCheck(); } - this.layoutService.update(); - this.cd.markForCheck(); - } - }); + }); - this.remoteParticipantsSubs = combineLatest([ + combineLatest([ this.participantService.remoteParticipants$, this.directiveService.layoutRemoteParticipants$ ]) .pipe( map(([serviceParticipants, directiveParticipants]) => directiveParticipants !== undefined ? directiveParticipants : serviceParticipants - ) + ), + takeUntil(this.destroy$) ) .subscribe((participants) => { this.remoteParticipants = participants; @@ -218,7 +218,10 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { this.videoIsAtRight = false; } }; - this.cdkSubscription = this.cdkDrag.released.subscribe(handler); + + this.cdkDrag.released + .pipe(takeUntil(this.destroy$)) + .subscribe(handler); if (this.globalService.isProduction()) return; // Just for allow E2E testing with drag and drop diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/activities-panel.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/activities-panel.component.ts index c53eee7b..3ae0c8f2 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/activities-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/activities-panel.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { PanelStatusInfo, PanelType } from '../../../models/panel.model'; import { OpenViduComponentsConfigService } from '../../../services/config/directive-config.service'; import { PanelService } from '../../../services/panel/panel.service'; @@ -80,9 +80,7 @@ export class ActivitiesPanelComponent implements OnInit { * @internal */ showBroadcastingActivity: boolean = true; - private panelSubscription: Subscription; - private recordingActivitySub: Subscription; - private broadcastingActivitySub: Subscription; + private destroy$ = new Subject(); /** * @internal @@ -105,9 +103,8 @@ export class ActivitiesPanelComponent implements OnInit { * @internal */ ngOnDestroy() { - if (this.panelSubscription) this.panelSubscription.unsubscribe(); - if (this.recordingActivitySub) this.recordingActivitySub.unsubscribe(); - if (this.broadcastingActivitySub) this.broadcastingActivitySub.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } /** @@ -118,7 +115,7 @@ export class ActivitiesPanelComponent implements OnInit { } private subscribeToPanelToggling() { - this.panelSubscription = this.panelService.panelStatusObs.subscribe((ev: PanelStatusInfo) => { + this.panelService.panelStatusObs.pipe(takeUntil(this.destroy$)).subscribe((ev: PanelStatusInfo) => { if (ev.panelType === PanelType.ACTIVITIES && !!ev.subOptionType) { this.expandedPanel = ev.subOptionType; } @@ -126,12 +123,12 @@ export class ActivitiesPanelComponent implements OnInit { } private subscribeToActivitiesPanelDirective() { - this.recordingActivitySub = this.libService.recordingActivity$.subscribe((value: boolean) => { + this.libService.recordingActivity$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showRecordingActivity = value; this.cd.markForCheck(); }); - this.broadcastingActivitySub = this.libService.broadcastingActivity$.subscribe((value: boolean) => { + this.libService.broadcastingActivity$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showBroadcastingActivity = value; this.cd.markForCheck(); }); diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component.ts index 7fd7ea2c..ed2f581d 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { BroadcastingStartRequestedEvent, BroadcastingStatus, @@ -76,7 +76,7 @@ export class BroadcastingActivityComponent implements OnInit { */ isPanelOpened: boolean = false; - private broadcastingSub: Subscription; + private destroy$ = new Subject(); /** * @internal @@ -99,7 +99,8 @@ export class BroadcastingActivityComponent implements OnInit { * @internal */ ngOnDestroy() { - if (this.broadcastingSub) this.broadcastingSub.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } /** @@ -147,7 +148,7 @@ export class BroadcastingActivityComponent implements OnInit { } private subscribeToBroadcastingStatus() { - this.broadcastingSub = this.broadcastingService.broadcastingStatusObs.subscribe((event: BroadcastingStatusInfo | undefined) => { + this.broadcastingService.broadcastingStatusObs.pipe(takeUntil(this.destroy$)).subscribe((event: BroadcastingStatusInfo | undefined) => { if (!!event) { const { status, broadcastingId, error } = event; this.broadcastingStatus = status; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/recording-activity/recording-activity.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/recording-activity/recording-activity.component.ts index 56e09cec..76ebfcbb 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/recording-activity/recording-activity.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/activities-panel/recording-activity/recording-activity.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { RecordingDeleteRequestedEvent, RecordingDownloadClickedEvent, @@ -109,8 +109,7 @@ export class RecordingActivityComponent implements OnInit { */ mouseHovering: boolean = false; private log: ILogger; - private recordingStatusSubscription: Subscription; - private tracksSubscription: Subscription; + private destroy$ = new Subject(); /** * @internal @@ -138,8 +137,8 @@ export class RecordingActivityComponent implements OnInit { * @internal */ ngOnDestroy() { - if (this.recordingStatusSubscription) this.recordingStatusSubscription.unsubscribe(); - if (this.tracksSubscription) this.tracksSubscription.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } /** @@ -242,7 +241,7 @@ export class RecordingActivityComponent implements OnInit { } private subscribeToRecordingStatus() { - this.recordingStatusSubscription = this.recordingService.recordingStatusObs.subscribe((event: RecordingStatusInfo) => { + this.recordingService.recordingStatusObs.pipe(takeUntil(this.destroy$)).subscribe((event: RecordingStatusInfo) => { const { status, recordingList, error } = event; this.recordingStatus = status; this.recordingList = recordingList; @@ -258,7 +257,7 @@ export class RecordingActivityComponent implements OnInit { private subscribeToTracksChanges() { this.hasRoomTracksPublished = this.openviduService.hasRoomTracksPublished(); - this.tracksSubscription = this.participantService.localParticipant$.subscribe(() => { + this.participantService.localParticipant$.pipe(takeUntil(this.destroy$)).subscribe(() => { const newValue = this.openviduService.hasRoomTracksPublished(); if (this.hasRoomTracksPublished !== newValue) { this.hasRoomTracksPublished = newValue; @@ -266,7 +265,7 @@ export class RecordingActivityComponent implements OnInit { } }); - this.participantService.remoteParticipants$.subscribe(() => { + this.participantService.remoteParticipants$.pipe(takeUntil(this.destroy$)).subscribe(() => { const newValue = this.openviduService.hasRoomTracksPublished(); if (this.hasRoomTracksPublished !== newValue) { this.hasRoomTracksPublished = newValue; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts index 1cc7d5cd..ad80a871 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { ChatMessage } from '../../../models/chat.model'; import { PanelType } from '../../../models/panel.model'; import { ChatService } from '../../../services/chat/chat.service'; @@ -34,7 +34,7 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { */ messageList: ChatMessage[] = []; - private chatMessageSubscription: Subscription; + private destroy$ = new Subject(); /** * @ignore @@ -66,7 +66,8 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { * @ignore */ ngOnDestroy(): void { - if (this.chatMessageSubscription) this.chatMessageSubscription.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } /** @@ -109,7 +110,7 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { } private subscribeToMessages() { - this.chatMessageSubscription = this.chatService.messagesObs.subscribe((messages: ChatMessage[]) => { + this.chatService.messagesObs.pipe(takeUntil(this.destroy$)).subscribe((messages: ChatMessage[]) => { this.messageList = messages; if (this.panelService.isChatPanelOpened()) { this.scrollToBottom(); diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/panel.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/panel.component.ts index e2207cad..31729ff4 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/panel.component.ts @@ -8,7 +8,7 @@ import { Output, TemplateRef } from '@angular/core'; -import { skip, Subscription } from 'rxjs'; +import { skip, Subject, takeUntil } from 'rxjs'; import { ActivitiesPanelDirective, AdditionalPanelsDirective, @@ -195,7 +195,7 @@ export class PanelComponent implements OnInit { * @internal */ isExternalPanelOpened: boolean; - private panelSubscription: Subscription; + private destroy$ = new Subject(); private panelEmitersHandler: Map< PanelType, @@ -226,11 +226,12 @@ export class PanelComponent implements OnInit { ngOnDestroy() { this.isChatPanelOpened = false; this.isParticipantsPanelOpened = false; - if (this.panelSubscription) this.panelSubscription.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } private subscribeToPanelToggling() { - this.panelSubscription = this.panelService.panelStatusObs.pipe(skip(1)).subscribe((ev: PanelStatusInfo) => { + this.panelService.panelStatusObs.pipe(skip(1), takeUntil(this.destroy$)).subscribe((ev: PanelStatusInfo) => { this.isChatPanelOpened = ev.isOpened && ev.panelType === PanelType.CHAT; this.isParticipantsPanelOpened = ev.isOpened && ev.panelType === PanelType.PARTICIPANTS; this.isBackgroundEffectsPanelOpened = ev.isOpened && ev.panelType === PanelType.BACKGROUND_EFFECTS; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts index 88423651..627c7759 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { PanelStatusInfo, PanelSettingsOptions, PanelType } from '../../../models/panel.model'; import { OpenViduComponentsConfigService } from '../../../services/config/directive-config.service'; import { PanelService } from '../../../services/panel/panel.service'; @@ -27,11 +27,8 @@ export class SettingsPanelComponent implements OnInit { showCameraButton: boolean = true; showMicrophoneButton: boolean = true; showCaptions: boolean = true; - panelSubscription: Subscription; isMobile: boolean = false; - private cameraButtonSub: Subscription; - private microphoneButtonSub: Subscription; - private captionsSubs: Subscription; + private destroy$ = new Subject(); constructor( private panelService: PanelService, private platformService: PlatformService, @@ -44,10 +41,8 @@ export class SettingsPanelComponent implements OnInit { } ngOnDestroy() { - if (this.panelSubscription) this.panelSubscription.unsubscribe(); - if (this.cameraButtonSub) this.cameraButtonSub.unsubscribe(); - if (this.microphoneButtonSub) this.microphoneButtonSub.unsubscribe(); - if (this.captionsSubs) this.captionsSubs.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); } close() { @@ -58,13 +53,13 @@ export class SettingsPanelComponent implements OnInit { } private subscribeToDirectives() { - this.cameraButtonSub = this.libService.cameraButton$.subscribe((value: boolean) => (this.showCameraButton = value)); - this.microphoneButtonSub = this.libService.microphoneButton$.subscribe((value: boolean) => (this.showMicrophoneButton = value)); - this.captionsSubs = this.libService.captionsButton$.subscribe((value: boolean) => (this.showCaptions = value)); + this.libService.cameraButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => (this.showCameraButton = value)); + this.libService.microphoneButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => (this.showMicrophoneButton = value)); + this.libService.captionsButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => (this.showCaptions = value)); } private subscribeToPanelToggling() { - this.panelSubscription = this.panelService.panelStatusObs.subscribe((ev: PanelStatusInfo) => { + this.panelService.panelStatusObs.pipe(takeUntil(this.destroy$)).subscribe((ev: PanelStatusInfo) => { if (ev.panelType === PanelType.SETTINGS && !!ev.subOptionType) { this.selectedOption = ev.subOptionType as PanelSettingsOptions; } diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/pre-join/pre-join.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/pre-join/pre-join.component.ts index 5b9bc5e9..9d4958a0 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/pre-join/pre-join.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/pre-join/pre-join.component.ts @@ -9,7 +9,7 @@ import { OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } 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'; @@ -61,11 +61,7 @@ export class PreJoinComponent implements OnInit, OnDestroy { audioTrack: LocalTrack | undefined; private tracks: LocalTrack[]; private log: ILogger; - private cameraButtonSub: Subscription; - private microphoneButtonSub: Subscription; - private minimalSub: Subscription; - private displayLogoSub: Subscription; - private displayParticipantNameSub: Subscription; + private destroy$ = new Subject(); private shouldRemoveTracksWhenComponentIsDestroyed: boolean = true; @HostListener('window:resize') @@ -99,12 +95,9 @@ export class PreJoinComponent implements OnInit, OnDestroy { // } async ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); this.cdkSrv.setSelector('body'); - if (this.minimalSub) this.minimalSub.unsubscribe(); - if (this.cameraButtonSub) this.cameraButtonSub.unsubscribe(); - if (this.microphoneButtonSub) this.microphoneButtonSub.unsubscribe(); - if (this.displayLogoSub) this.displayLogoSub.unsubscribe(); - if (this.displayParticipantNameSub) this.displayParticipantNameSub.unsubscribe(); if (this.shouldRemoveTracksWhenComponentIsDestroyed) { this.tracks.forEach((track) => { @@ -154,32 +147,49 @@ export class PreJoinComponent implements OnInit, OnDestroy { } private subscribeToPrejoinDirectives() { - this.minimalSub = this.libService.minimal$.subscribe((value: boolean) => { - this.isMinimal = value; - this.changeDetector.markForCheck(); - }); - this.cameraButtonSub = this.libService.cameraButton$.subscribe((value: boolean) => { - this.showCameraButton = value; - this.changeDetector.markForCheck(); - }); - this.microphoneButtonSub = this.libService.microphoneButton$.subscribe((value: boolean) => { - this.showMicrophoneButton = value; - this.changeDetector.markForCheck(); - }); - this.displayLogoSub = this.libService.displayLogo$.subscribe((value: boolean) => { - this.showLogo = value; - this.changeDetector.markForCheck(); - }); - this.libService.participantName$.subscribe((value: string) => { - if (value) { - this.participantName = value; + this.libService.minimal$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.isMinimal = value; this.changeDetector.markForCheck(); - } - }); - this.displayParticipantNameSub = this.libService.prejoinDisplayParticipantName$.subscribe((value: boolean) => { - this.showParticipantName = value; - this.changeDetector.markForCheck(); - }); + }); + + this.libService.cameraButton$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showCameraButton = value; + this.changeDetector.markForCheck(); + }); + + this.libService.microphoneButton$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showMicrophoneButton = value; + this.changeDetector.markForCheck(); + }); + + this.libService.displayLogo$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showLogo = value; + this.changeDetector.markForCheck(); + }); + + this.libService.participantName$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: string) => { + if (value) { + this.participantName = value; + this.changeDetector.markForCheck(); + } + }); + + this.libService.prejoinDisplayParticipantName$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showParticipantName = value; + this.changeDetector.markForCheck(); + }); } async videoEnabledChanged(enabled: boolean) { diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/session/session.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/session/session.component.ts index c4139a3d..9ea87202 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/session/session.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/session/session.component.ts @@ -16,7 +16,7 @@ import { import { ILogger } from '../../models/logger.model'; import { animate, style, transition, trigger } from '@angular/animations'; import { MatDrawerContainer, MatSidenav } from '@angular/material/sidenav'; -import { skip, Subscription } from 'rxjs'; +import { skip, Subject, takeUntil } from 'rxjs'; import { SidenavMode } from '../../models/layout.model'; import { PanelStatusInfo, PanelType } from '../../models/panel.model'; import { DataTopic } from '../../models/data-topic.model'; @@ -105,10 +105,8 @@ export class SessionComponent implements OnInit, OnDestroy { private shouldDisconnectRoomWhenComponentIsDestroyed: boolean = true; private readonly SIDENAV_WIDTH_LIMIT_MODE = 790; - private menuSubscription: Subscription; - private layoutWidthSubscription: Subscription; + private destroy$ = new Subject(); private updateLayoutInterval: NodeJS.Timeout; - private captionLanguageSubscription: Subscription; private log: ILogger; constructor( @@ -238,8 +236,8 @@ export class SessionComponent implements OnInit, OnDestroy { if (this.room) this.room.removeAllListeners(); this.participantService.clear(); // this.room = undefined; - if (this.menuSubscription) this.menuSubscription.unsubscribe(); - if (this.layoutWidthSubscription) this.layoutWidthSubscription.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); // if (this.captionLanguageSubscription) this.captionLanguageSubscription.unsubscribe(); } @@ -269,7 +267,7 @@ export class SessionComponent implements OnInit, OnDestroy { this.startUpdateLayoutInterval(); }); - this.menuSubscription = this.panelService.panelStatusObs.pipe(skip(1)).subscribe((ev: PanelStatusInfo) => { + this.panelService.panelStatusObs.pipe(skip(1), takeUntil(this.destroy$)).subscribe((ev: PanelStatusInfo) => { if (this.sideMenu) { this.settingsPanelOpened = ev.isOpened && ev.panelType === PanelType.SETTINGS; @@ -288,7 +286,7 @@ export class SessionComponent implements OnInit, OnDestroy { } private subscribeToLayoutWidth() { - this.layoutWidthSubscription = this.layoutService.layoutWidthObs.subscribe((width) => { + this.layoutService.layoutWidthObs.pipe(takeUntil(this.destroy$)).subscribe((width) => { this.sidenavMode = width <= this.SIDENAV_WIDTH_LIMIT_MODE ? SidenavMode.OVER : SidenavMode.SIDE; }); } diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/stream/stream.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/stream/stream.component.ts index 6f9495c6..21231b97 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/stream/stream.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/stream/stream.component.ts @@ -1,6 +1,6 @@ import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { MatMenuPanel, MatMenuTrigger } from '@angular/material/menu'; -import { Subscription } from 'rxjs'; +import { Subject, takeUntil } from 'rxjs'; import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service'; import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service'; import { LayoutService } from '../../services/layout/layout.service'; @@ -92,10 +92,7 @@ export class StreamComponent implements OnInit, OnDestroy { } private _streamContainer: ElementRef; - private minimalSub: Subscription; - private displayParticipantNameSub: Subscription; - private displayAudioDetectionSub: Subscription; - private videoControlsSub: Subscription; + private destroy$ = new Subject(); private readonly HOVER_TIMEOUT = 3000; /** @@ -113,11 +110,9 @@ export class StreamComponent implements OnInit, OnDestroy { } ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); this.cdkSrv.setSelector('body'); - if (this.videoControlsSub) this.videoControlsSub.unsubscribe(); - if (this.displayAudioDetectionSub) this.displayAudioDetectionSub.unsubscribe(); - if (this.displayParticipantNameSub) this.displayParticipantNameSub.unsubscribe(); - if (this.minimalSub) this.minimalSub.unsubscribe(); } /** @@ -183,20 +178,31 @@ export class StreamComponent implements OnInit, OnDestroy { } private subscribeToStreamDirectives() { - this.minimalSub = this.libService.minimal$.subscribe((value: boolean) => { - this.isMinimal = value; - }); - this.displayParticipantNameSub = this.libService.displayParticipantName$.subscribe((value: boolean) => { - this.showParticipantName = value; - // this.cd.markForCheck(); - }); - this.displayAudioDetectionSub = this.libService.displayAudioDetection$.subscribe((value: boolean) => { - this.showAudioDetection = value; - // this.cd.markForCheck(); - }); - this.videoControlsSub = this.libService.streamVideoControls$.subscribe((value: boolean) => { - this.showVideoControls = value; - // this.cd.markForCheck(); - }); + this.libService.minimal$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.isMinimal = value; + }); + + this.libService.displayParticipantName$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showParticipantName = value; + // this.cd.markForCheck(); + }); + + this.libService.displayAudioDetection$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showAudioDetection = value; + // this.cd.markForCheck(); + }); + + this.libService.streamVideoControls$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showVideoControls = value; + // this.cd.markForCheck(); + }); } } diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.ts index 360a9cea..728f6c83 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.ts @@ -12,7 +12,7 @@ import { TemplateRef, ViewChild } from '@angular/core'; -import { fromEvent, skip, Subscription } from 'rxjs'; +import { fromEvent, skip, Subject, takeUntil } from 'rxjs'; import { ChatService } from '../../services/chat/chat.service'; import { DocumentService } from '../../services/document/document.service'; import { PanelService } from '../../services/panel/panel.service'; @@ -340,30 +340,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { recordingTime: Date; private log: ILogger; - private minimalSub: Subscription; - private panelTogglingSubscription: Subscription; - private chatMessagesSubscription: Subscription; - private localParticipantSubscription: Subscription; - private cameraButtonSub: Subscription; - private microphoneButtonSub: Subscription; - private screenshareButtonSub: Subscription; - private fullscreenButtonSub: Subscription; - private backgroundEffectsButtonSub: Subscription; - private leaveButtonSub: Subscription; - private recordingButtonSub: Subscription; - private broadcastingButtonSub: Subscription; - private recordingSubscription: Subscription; - private broadcastingSubscription: Subscription; - private activitiesPanelButtonSub: Subscription; - private participantsPanelButtonSub: Subscription; - private chatPanelButtonSub: Subscription; - private displayLogoSub: Subscription; - private brandingLogoSub: Subscription; - private displayRoomNameSub: Subscription; - private settingsButtonSub: Subscription; - private captionsSubs: Subscription; - private additionalButtonsPositionSub: Subscription; - private fullscreenChangeSubscription: Subscription; + private destroy$ = new Subject(); private currentWindowHeight = window.innerHeight; /** @@ -437,30 +414,8 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { ngOnDestroy(): void { this.panelService.clear(); - if (this.panelTogglingSubscription) this.panelTogglingSubscription.unsubscribe(); - if (this.chatMessagesSubscription) this.chatMessagesSubscription.unsubscribe(); - if (this.localParticipantSubscription) this.localParticipantSubscription.unsubscribe(); - if (this.cameraButtonSub) this.cameraButtonSub.unsubscribe(); - if (this.microphoneButtonSub) this.microphoneButtonSub.unsubscribe(); - if (this.screenshareButtonSub) this.screenshareButtonSub.unsubscribe(); - if (this.fullscreenButtonSub) this.fullscreenButtonSub.unsubscribe(); - if (this.backgroundEffectsButtonSub) this.backgroundEffectsButtonSub.unsubscribe(); - if (this.leaveButtonSub) this.leaveButtonSub.unsubscribe(); - if (this.recordingButtonSub) this.recordingButtonSub.unsubscribe(); - if (this.broadcastingButtonSub) this.broadcastingButtonSub.unsubscribe(); - if (this.participantsPanelButtonSub) this.participantsPanelButtonSub.unsubscribe(); - if (this.chatPanelButtonSub) this.chatPanelButtonSub.unsubscribe(); - if (this.displayLogoSub) this.displayLogoSub.unsubscribe(); - if (this.brandingLogoSub) this.brandingLogoSub.unsubscribe(); - if (this.displayRoomNameSub) this.displayRoomNameSub.unsubscribe(); - if (this.minimalSub) this.minimalSub.unsubscribe(); - if (this.activitiesPanelButtonSub) this.activitiesPanelButtonSub.unsubscribe(); - if (this.recordingSubscription) this.recordingSubscription.unsubscribe(); - if (this.broadcastingSubscription) this.broadcastingSubscription.unsubscribe(); - if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe(); - if (this.captionsSubs) this.captionsSubs.unsubscribe(); - if (this.fullscreenChangeSubscription) this.fullscreenChangeSubscription.unsubscribe(); - if (this.additionalButtonsPositionSub) this.additionalButtonsPositionSub.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); this.isFullscreenActive = false; this.cdkOverlayService.setSelector('body'); } @@ -647,7 +602,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToFullscreenChanged() { - this.fullscreenChangeSubscription = fromEvent(document, 'fullscreenchange').subscribe(() => { + fromEvent(document, 'fullscreenchange').pipe(takeUntil(this.destroy$)).subscribe(() => { const isFullscreen = Boolean(document.fullscreenElement); if (isFullscreen) { this.cdkOverlayService.setSelector('#session-container'); @@ -661,7 +616,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToMenuToggling() { - this.panelTogglingSubscription = this.panelService.panelStatusObs.subscribe((ev: PanelStatusInfo) => { + this.panelService.panelStatusObs.pipe(takeUntil(this.destroy$)).subscribe((ev: PanelStatusInfo) => { this.isChatOpened = ev.isOpened && ev.panelType === PanelType.CHAT; this.isParticipantsOpened = ev.isOpened && ev.panelType === PanelType.PARTICIPANTS; this.isActivitiesOpened = ev.isOpened && ev.panelType === PanelType.ACTIVITIES; @@ -673,7 +628,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToChatMessages() { - this.chatMessagesSubscription = this.chatService.messagesObs.pipe(skip(1)).subscribe((messages) => { + this.chatService.messagesObs.pipe(skip(1), takeUntil(this.destroy$)).subscribe((messages) => { if (!this.panelService.isChatPanelOpened()) { this.unreadMessages++; } @@ -682,7 +637,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { }); } private subscribeToUserMediaProperties() { - this.localParticipantSubscription = this.participantService.localParticipant$.subscribe((p: ParticipantModel | undefined) => { + this.participantService.localParticipant$.pipe(takeUntil(this.destroy$)).subscribe((p: ParticipantModel | undefined) => { if (p) { if (this.isCameraEnabled !== p.isCameraEnabled) { this.onVideoEnabledChanged.emit(p.isCameraEnabled); @@ -706,7 +661,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToRecordingStatus() { - this.recordingSubscription = this.recordingService.recordingStatusObs.subscribe((event: RecordingStatusInfo) => { + this.recordingService.recordingStatusObs.pipe(takeUntil(this.destroy$)).subscribe((event: RecordingStatusInfo) => { const { status, startedAt } = event; this.recordingStatus = status; if (status === RecordingStatus.STARTED) { @@ -723,7 +678,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToBroadcastingStatus() { - this.broadcastingSubscription = this.broadcastingService.broadcastingStatusObs.subscribe((ev: BroadcastingStatusInfo) => { + this.broadcastingService.broadcastingStatusObs.pipe(takeUntil(this.destroy$)).subscribe((ev: BroadcastingStatusInfo) => { if (!!ev) { this.broadcastingStatus = ev.status; this.broadcastingId = ev.broadcastingId; @@ -733,85 +688,85 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToToolbarDirectives() { - this.minimalSub = this.libService.minimal$.subscribe((value: boolean) => { + this.libService.minimal$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.isMinimal = value; this.cd.markForCheck(); }); - this.brandingLogoSub = this.libService.brandingLogo$.subscribe((value: string) => { + this.libService.brandingLogo$.pipe(takeUntil(this.destroy$)).subscribe((value: string) => { this.brandingLogo = value; this.cd.markForCheck(); }); - this.cameraButtonSub = this.libService.cameraButton$.subscribe((value: boolean) => { + this.libService.cameraButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showCameraButton = value; this.cd.markForCheck(); }); - this.microphoneButtonSub = this.libService.microphoneButton$.subscribe((value: boolean) => { + this.libService.microphoneButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showMicrophoneButton = value; this.cd.markForCheck(); }); - this.screenshareButtonSub = this.libService.screenshareButton$.subscribe((value: boolean) => { + this.libService.screenshareButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showScreenshareButton = value && !this.platformService.isMobile(); this.cd.markForCheck(); }); - this.fullscreenButtonSub = this.libService.fullscreenButton$.subscribe((value: boolean) => { + this.libService.fullscreenButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showFullscreenButton = value; this.checkDisplayMoreOptions(); this.cd.markForCheck(); }); - this.leaveButtonSub = this.libService.leaveButton$.subscribe((value: boolean) => { + this.libService.leaveButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showLeaveButton = value; this.cd.markForCheck(); }); - this.recordingButtonSub = this.libService.recordingButton$.subscribe((value: boolean) => { + this.libService.recordingButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showRecordingButton = value; this.checkDisplayMoreOptions(); this.cd.markForCheck(); }); - this.broadcastingButtonSub = this.libService.broadcastingButton$.subscribe((value: boolean) => { + this.libService.broadcastingButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showBroadcastingButton = value; this.checkDisplayMoreOptions(); this.cd.markForCheck(); }); - this.settingsButtonSub = this.libService.toolbarSettingsButton$.subscribe((value: boolean) => { + this.libService.toolbarSettingsButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showSettingsButton = value; this.checkDisplayMoreOptions(); this.cd.markForCheck(); }); - this.chatPanelButtonSub = this.libService.chatPanelButton$.subscribe((value: boolean) => { + this.libService.chatPanelButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showChatPanelButton = value; this.cd.markForCheck(); }); - this.participantsPanelButtonSub = this.libService.participantsPanelButton$.subscribe((value: boolean) => { + this.libService.participantsPanelButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showParticipantsPanelButton = value; this.cd.markForCheck(); }); - this.activitiesPanelButtonSub = this.libService.activitiesPanelButton$.subscribe((value: boolean) => { + this.libService.activitiesPanelButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showActivitiesPanelButton = value; this.cd.markForCheck(); }); - this.backgroundEffectsButtonSub = this.libService.backgroundEffectsButton$.subscribe((value: boolean) => { + this.libService.backgroundEffectsButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showBackgroundEffectsButton = value; this.checkDisplayMoreOptions(); this.cd.markForCheck(); }); - this.displayLogoSub = this.libService.displayLogo$.subscribe((value: boolean) => { + this.libService.displayLogo$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showLogo = value; this.cd.markForCheck(); }); - this.displayRoomNameSub = this.libService.displayRoomName$.subscribe((value: boolean) => { + this.libService.displayRoomName$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showSessionName = value; this.cd.markForCheck(); }); - this.captionsSubs = this.libService.captionsButton$.subscribe((value: boolean) => { + this.libService.captionsButton$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.showCaptionsButton = value; this.cd.markForCheck(); }); - this.additionalButtonsPositionSub = this.libService.toolbarAdditionalButtonsPosition$.subscribe( + this.libService.toolbarAdditionalButtonsPosition$.pipe(takeUntil(this.destroy$)).subscribe( (value: ToolbarAdditionalButtonsPosition) => { // Using Promise.resolve() to defer change detection until the next microtask. // This ensures that Angular's change detection has the latest value before updating the view. @@ -827,7 +782,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { } private subscribeToCaptionsToggling() { - this.captionsSubs = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => { + this.layoutService.captionsTogglingObs.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => { this.captionsEnabled = value; this.cd.markForCheck(); }); diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.ts index 7ebe9842..4fd618ee 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.ts @@ -1,6 +1,6 @@ import { animate, style, transition, trigger } from '@angular/animations'; import { AfterViewInit, Component, ContentChild, EventEmitter, OnDestroy, Output, TemplateRef, ViewChild } from '@angular/core'; -import { Subscription, filter, skip, take } from 'rxjs'; +import { Subject, filter, skip, take, takeUntil } from 'rxjs'; import { ActivitiesPanelDirective, AdditionalPanelsDirective, @@ -379,10 +379,8 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { * @internal */ _tokenError: any; - private prejoinSub: Subscription; - private tokenSub: Subscription; - private tokenErrorSub: Subscription; - private participantNameSub: Subscription; + + private destroy$ = new Subject(); private log: ILogger; private latestParticipantName: string | undefined; @@ -402,10 +400,8 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { } ngOnDestroy() { - if (this.prejoinSub) this.prejoinSub.unsubscribe(); - if (this.participantNameSub) this.participantNameSub.unsubscribe(); - if (this.tokenSub) this.tokenSub.unsubscribe(); - if (this.tokenErrorSub) this.tokenErrorSub.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); this.deviceSrv.clear(); } @@ -599,79 +595,91 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { } private subscribeToVideconferenceDirectives() { - this.tokenSub = this.libService.token$.pipe(skip(1)).subscribe((token: string) => { - try { - if (!token) { - this.log.e('Token is empty'); - return; - } + this.libService.token$ + .pipe( + skip(1), + takeUntil(this.destroy$) + ) + .subscribe((token: string) => { + try { + if (!token) { + this.log.e('Token is empty'); + return; + } - const livekitUrl = this.libService.getLivekitUrl(); - this.openviduService.initializeAndSetToken(token, livekitUrl); - this.log.d('Token has been successfully set. Room is ready to join'); - this.isRoomReady = true; - this.showPrejoin = false; - } catch (error) { - this.log.e('Error trying to set token', error); + const livekitUrl = this.libService.getLivekitUrl(); + this.openviduService.initializeAndSetToken(token, livekitUrl); + this.log.d('Token has been successfully set. Room is ready to join'); + this.isRoomReady = true; + this.showPrejoin = false; + } catch (error) { + this.log.e('Error trying to set token', error); + this._tokenError = error; + } + }); + + this.libService.tokenError$ + .pipe(takeUntil(this.destroy$)) + .subscribe((error: any) => { + if (!error) return; + + this.log.e('Token error received', error); this._tokenError = error; - } - }); - this.tokenErrorSub = this.libService.tokenError$.subscribe((error: any) => { - if (!error) return; - - this.log.e('Token error received', error); - this._tokenError = error; - - if (!this.showPrejoin) { - this.actionService.openDialog(error.name, error.message, false); - } - }); - this.prejoinSub = this.libService.prejoin$.subscribe((value: boolean) => { - this.showPrejoin = value; - if (!this.showPrejoin) { - // Emit token ready if the prejoin page won't be shown - - // Ensure we have a participant name before proceeding with the join - this.log.d('Prejoin page is hidden, checking participant name'); - // Check if we have a participant name already - if (this.latestParticipantName) { - // We have a name, proceed immediately - this._onReadyToJoin(); - } else { - // No name yet - set up a one-time subscription to wait for it - const waitForNameSub = this.libService.participantName$ - .pipe( - filter((name) => !!name), - take(1) - ) - .subscribe(() => { - // Now we have the name in latestParticipantName - this._onReadyToJoin(); - }); - // Add safety timeout in case name never arrives - setTimeout(() => { - if (!this.latestParticipantName) { - this.log.w('No participant name received after timeout, proceeding anyway'); - waitForNameSub.unsubscribe(); - const storedName = this.storageSrv.getParticipantName(); - if (storedName) { - this.latestParticipantName = storedName; - this.libService.setParticipantName(storedName); - } - this._onReadyToJoin(); - } - }, 1000); + if (!this.showPrejoin) { + this.actionService.openDialog(error.name, error.message, false); } - } - // this.cd.markForCheck(); - }); + }); - this.participantNameSub = this.libService.participantName$.subscribe((name: string) => { - if (name) { - this.latestParticipantName = name; - this.storageSrv.setParticipantName(name); - } - }); + this.libService.prejoin$ + .pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + this.showPrejoin = value; + if (!this.showPrejoin) { + // Emit token ready if the prejoin page won't be shown + + // Ensure we have a participant name before proceeding with the join + this.log.d('Prejoin page is hidden, checking participant name'); + // Check if we have a participant name already + if (this.latestParticipantName) { + // We have a name, proceed immediately + this._onReadyToJoin(); + } else { + // No name yet - set up a one-time subscription to wait for it + this.libService.participantName$ + .pipe( + filter((name) => !!name), + take(1), + takeUntil(this.destroy$) + ) + .subscribe(() => { + // Now we have the name in latestParticipantName + this._onReadyToJoin(); + }); + // Add safety timeout in case name never arrives + setTimeout(() => { + if (!this.latestParticipantName) { + this.log.w('No participant name received after timeout, proceeding anyway'); + const storedName = this.storageSrv.getParticipantName(); + if (storedName) { + this.latestParticipantName = storedName; + this.libService.setParticipantName(storedName); + } + this._onReadyToJoin(); + } + }, 1000); + } + } + // this.cd.markForCheck(); + }); + + this.libService.participantName$ + .pipe(takeUntil(this.destroy$)) + .subscribe((name: string) => { + if (name) { + this.latestParticipantName = name; + this.storageSrv.setParticipantName(name); + } + }); } }