ov-components: implement showThemeSelector directive and integrate theme selector functionality

master
Carlos Santos 2025-09-25 17:03:07 +02:00
parent 0cdb46a79c
commit fe97022182
8 changed files with 87 additions and 11 deletions

View File

@ -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();
});
});

View File

@ -82,6 +82,7 @@
</mat-list-item>
</mat-list>
</div>
@if (showThemeSelector) {
<div class="theme-section">
<mat-list>
<mat-list-item class="theme-selector">
@ -91,6 +92,7 @@
</mat-list-item>
</mat-list>
</div>
}
</div>
<div *ngIf="showCameraButton && selectedOption === settingsOptions.VIDEO" class="video-settings">
<ov-video-devices-select

View File

@ -28,6 +28,7 @@ export class SettingsPanelComponent implements OnInit {
showCameraButton: boolean = true;
showMicrophoneButton: boolean = true;
showCaptions: boolean = true;
showThemeSelector: boolean = false;
isMobile: boolean = false;
private destroy$ = new Subject<void>();
@ -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() {

View File

@ -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({

View File

@ -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:
* <ov-videoconference [showThemeSelector]="false"></ov-videoconference>
*/
@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 });
}
}

View File

@ -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<boolean> = this.generalConfig.observable$.pipe(
map((config) => config.showThemeSelector),
distinctUntilChanged(),
shareReplay(1)
);
recordingStreamBaseUrl$: Observable<string> = this.generalConfig.observable$.pipe(
map((config) => config.recordingStreamBaseUrl),
distinctUntilChanged(),

View File

@ -12,6 +12,7 @@
[participantName]="participantName"
[videoEnabled]="videoEnabled"
[audioEnabled]="audioEnabled"
[showThemeSelector]="showThemeSelector"
[toolbarCameraButton]="toolbarCameraButton"
[toolbarMicrophoneButton]="toolbarMicrophoneButton"
[toolbarScreenshareButton]="toolbarScreenshareButton"

View File

@ -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) {