From fe97022182add8d7e9a80ea0025ce6942e072adf Mon Sep 17 00:00:00 2001
From: Carlos Santos <4a.santos@gmail.com>
Date: Thu, 25 Sep 2025 17:03:07 +0200
Subject: [PATCH] ov-components: implement showThemeSelector directive and
integrate theme selector functionality
---
.../e2e/internal-directives.test.ts | 13 ++++++
.../settings-panel.component.html | 20 ++++----
.../settings-panel.component.ts | 2 +
.../directives/api/api.directive.module.ts | 6 ++-
.../lib/directives/api/internals.directive.ts | 46 +++++++++++++++++++
.../config/directive-config.service.ts | 8 ++++
.../src/app/openvidu-call/call.component.html | 1 +
.../src/app/openvidu-call/call.component.ts | 2 +
8 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/openvidu-components-angular/e2e/internal-directives.test.ts b/openvidu-components-angular/e2e/internal-directives.test.ts
index 0cbab76c..79f2991f 100644
--- a/openvidu-components-angular/e2e/internal-directives.test.ts
+++ b/openvidu-components-angular/e2e/internal-directives.test.ts
@@ -81,4 +81,17 @@ describe('Testing Internal Directives', () => {
await utils.clickOn('#recording-activity');
expect(await utils.isPresent('#start-recording-btn')).toBeTrue();
});
+
+ it('should show/hide theme selector with showThemeSelector directive', async () => {
+ await browser.get(`${url}&prejoin=false&showThemeSelector=true`);
+ await utils.checkSessionIsPresent();
+ await utils.toggleToolbarMoreOptions();
+ expect(await utils.isPresent('.theme-selector-container')).toBeTrue();
+
+ await browser.get(`${url}&prejoin=false`);
+ await browser.navigate().refresh();
+ await utils.checkSessionIsPresent();
+ await utils.toggleToolbarMoreOptions();
+ expect(await utils.isPresent('.theme-selector-container')).toBeFalse();
+ });
});
diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.html b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.html
index ed6e5044..662e1594 100644
--- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.html
+++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/settings-panel/settings-panel.component.html
@@ -82,15 +82,17 @@
-
-
-
- routine
- {{ 'PANEL.SETTINGS.THEME' | translate }}
-
-
-
-
+ @if (showThemeSelector) {
+
+
+
+ routine
+ {{ 'PANEL.SETTINGS.THEME' | translate }}
+
+
+
+
+ }
();
@@ -72,6 +73,7 @@ export class SettingsPanelComponent implements OnInit {
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));
+ this.libService.showThemeSelector$.pipe(takeUntil(this.destroy$)).subscribe((value: boolean) => (this.showThemeSelector = value));
}
private subscribeToPanelToggling() {
diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/api.directive.module.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/api.directive.module.ts
index aee2a866..8206f336 100644
--- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/api.directive.module.ts
+++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/api.directive.module.ts
@@ -17,7 +17,8 @@ import {
StartStopRecordingButtonsDirective,
RecordingActivityViewRecordingsButtonDirective,
RecordingActivityShowRecordingsListDirective,
- ToolbarRoomNameDirective
+ ToolbarRoomNameDirective,
+ ShowThemeSelectorDirective
} from './internals.directive';
import { ParticipantPanelItemMuteButtonDirective } from './participant-panel-item.directive';
import {
@@ -111,7 +112,8 @@ const directives = [
StartStopRecordingButtonsDirective,
RecordingActivityViewRecordingsButtonDirective,
RecordingActivityShowRecordingsListDirective,
- ToolbarRoomNameDirective
+ ToolbarRoomNameDirective,
+ ShowThemeSelectorDirective
];
@NgModule({
diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/internals.directive.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/internals.directive.ts
index 203f29a1..7c47aaa5 100644
--- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/internals.directive.ts
+++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/api/internals.directive.ts
@@ -524,3 +524,49 @@ export class ToolbarRoomNameDirective implements AfterViewInit, OnDestroy {
this.libService.updateToolbarConfig({ roomName: this._roomName || '' });
}
}
+
+/**
+ * @internal
+ *
+ * The **showThemeSelector** directive allows to enable or disable the theme selector control.
+ * When disabled, users won't be able to change the UI theme.
+ *
+ * Default: `false`
+ *
+ * Usage:
+ *
+ */
+@Directive({
+ selector: 'ov-videoconference[showThemeSelector]',
+ standalone: false
+})
+export class ShowThemeSelectorDirective implements AfterViewInit, OnDestroy {
+ @Input() set showThemeSelector(value: boolean) {
+ this._value = value;
+ this.update(this._value);
+ }
+
+ private _value: boolean = false;
+
+ constructor(
+ public elementRef: ElementRef,
+ private libService: OpenViduComponentsConfigService
+ ) {}
+
+ ngAfterViewInit() {
+ this.update(this._value);
+ }
+
+ ngOnDestroy(): void {
+ this.clear();
+ }
+
+ private clear() {
+ this._value = true;
+ this.update(this._value);
+ }
+
+ private update(value: boolean) {
+ this.libService.updateGeneralConfig({ showThemeSelector: value });
+ }
+}
diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/config/directive-config.service.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/config/directive-config.service.ts
index 39f7154c..6985c762 100644
--- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/config/directive-config.service.ts
+++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/config/directive-config.service.ts
@@ -94,6 +94,7 @@ interface GeneralConfig {
prejoin: boolean;
prejoinDisplayParticipantName: boolean;
showDisconnectionDialog: boolean;
+ showThemeSelector: boolean;
recordingStreamBaseUrl: string;
}
@@ -300,6 +301,7 @@ export class OpenViduComponentsConfigService {
prejoin: true,
prejoinDisplayParticipantName: true,
showDisconnectionDialog: true,
+ showThemeSelector: false,
recordingStreamBaseUrl: 'call/api/recordings'
});
@@ -400,6 +402,12 @@ export class OpenViduComponentsConfigService {
distinctUntilChanged(),
shareReplay(1)
);
+
+ showThemeSelector$: Observable = this.generalConfig.observable$.pipe(
+ map((config) => config.showThemeSelector),
+ distinctUntilChanged(),
+ shareReplay(1)
+ );
recordingStreamBaseUrl$: Observable = this.generalConfig.observable$.pipe(
map((config) => config.recordingStreamBaseUrl),
distinctUntilChanged(),
diff --git a/openvidu-components-angular/src/app/openvidu-call/call.component.html b/openvidu-components-angular/src/app/openvidu-call/call.component.html
index 81b185bd..cfdb1213 100644
--- a/openvidu-components-angular/src/app/openvidu-call/call.component.html
+++ b/openvidu-components-angular/src/app/openvidu-call/call.component.html
@@ -12,6 +12,7 @@
[participantName]="participantName"
[videoEnabled]="videoEnabled"
[audioEnabled]="audioEnabled"
+ [showThemeSelector]="showThemeSelector"
[toolbarCameraButton]="toolbarCameraButton"
[toolbarMicrophoneButton]="toolbarMicrophoneButton"
[toolbarScreenshareButton]="toolbarScreenshareButton"
diff --git a/openvidu-components-angular/src/app/openvidu-call/call.component.ts b/openvidu-components-angular/src/app/openvidu-call/call.component.ts
index 5211e78f..c05adf24 100644
--- a/openvidu-components-angular/src/app/openvidu-call/call.component.ts
+++ b/openvidu-components-angular/src/app/openvidu-call/call.component.ts
@@ -66,6 +66,7 @@ export class CallComponent implements OnInit {
public recordingActivityStartStopRecordingButton: boolean = true;
toolbarViewRecordingsButton: boolean = false;
private redirectToHomeOnLeaves: boolean = true;
+ private showThemeSelector: boolean = false;
private staticVideos = [
'https://videos.pexels.com/video-files/4089575/4089575-hd_1280_720_50fps.mp4',
@@ -159,6 +160,7 @@ export class CallComponent implements OnInit {
} else {
this.redirectToHomeOnLeaves = params['redirectToHome'] === 'true';
}
+ if(params['showThemeSelector'] !== undefined) this.showThemeSelector = params['showThemeSelector'] === 'true';
this.configReady = true;
if (this.areStaticVideosEnabled) {