ov-componentes: Added ovToolbarAdditionalButtonsPosition directive

pull/839/head
Carlos Santos 2024-08-22 11:17:02 +02:00
parent 9f0246db2f
commit a82b2189bc
6 changed files with 112 additions and 4 deletions

View File

@ -91,6 +91,10 @@
</button> </button>
</mat-menu> </mat-menu>
<ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'beforeMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container>
<!-- More options button --> <!-- More options button -->
<button <button
mat-icon-button mat-icon-button
@ -187,7 +191,7 @@
</mat-menu> </mat-menu>
<!-- External additional buttons --> <!-- External additional buttons -->
<ng-container *ngIf="toolbarAdditionalButtonsTemplate"> <ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'afterMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container> <ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container> </ng-container>

View File

@ -48,6 +48,7 @@ import { TranslateService } from '../../services/translate/translate.service';
import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service'; import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service';
import { ParticipantModel } from '../../models/participant.model'; import { ParticipantModel } from '../../models/participant.model';
import { Room, RoomEvent } from 'livekit-client'; import { Room, RoomEvent } from 'livekit-client';
import { ToolbarAdditionalButtonsPosition } from '../../models/toolbar.model';
/** /**
* The **ToolbarComponent** is hosted inside of the {@link VideoconferenceComponent}. * The **ToolbarComponent** is hosted inside of the {@link VideoconferenceComponent}.
@ -75,7 +76,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
*/ */
@ContentChild(ToolbarAdditionalButtonsDirective) @ContentChild(ToolbarAdditionalButtonsDirective)
set externalAdditionalButtons(externalAdditionalButtons: ToolbarAdditionalButtonsDirective) { set externalAdditionalButtons(externalAdditionalButtons: ToolbarAdditionalButtonsDirective) {
// This directive will has value only when ADDITIONAL BUTTONS component tagget with '*ovToolbarAdditionalButtons' directive // This directive will has value only when ADDITIONAL BUTTONS component (tagged with '*ovToolbarAdditionalButtons' directive)
// is inside of the TOOLBAR component tagged with '*ovToolbar' directive // is inside of the TOOLBAR component tagged with '*ovToolbar' directive
if (externalAdditionalButtons) { if (externalAdditionalButtons) {
this.toolbarAdditionalButtonsTemplate = externalAdditionalButtons.template; this.toolbarAdditionalButtonsTemplate = externalAdditionalButtons.template;
@ -87,7 +88,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
*/ */
@ContentChild(ToolbarAdditionalPanelButtonsDirective) @ContentChild(ToolbarAdditionalPanelButtonsDirective)
set externalAdditionalPanelButtons(externalAdditionalPanelButtons: ToolbarAdditionalPanelButtonsDirective) { set externalAdditionalPanelButtons(externalAdditionalPanelButtons: ToolbarAdditionalPanelButtonsDirective) {
// This directive will has value only when ADDITIONAL PANEL BUTTONS component tagget with '*ovToolbarAdditionalPanelButtons' directive // This directive will has value only when ADDITIONAL PANEL BUTTONS component tagged with '*ovToolbarAdditionalPanelButtons' directive
// is inside of the TOOLBAR component tagged with '*ovToolbar' directive // is inside of the TOOLBAR component tagged with '*ovToolbar' directive
if (externalAdditionalPanelButtons) { if (externalAdditionalPanelButtons) {
this.toolbarAdditionalPanelButtonsTemplate = externalAdditionalPanelButtons.template; this.toolbarAdditionalPanelButtonsTemplate = externalAdditionalPanelButtons.template;
@ -266,6 +267,11 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
*/ */
showCaptionsButton: boolean = true; showCaptionsButton: boolean = true;
/**
* @ignore
*/
additionalButtonsPosition: ToolbarAdditionalButtonsPosition;
/** /**
* @ignore * @ignore
*/ */
@ -333,6 +339,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
private displayRoomNameSub: Subscription; private displayRoomNameSub: Subscription;
private settingsButtonSub: Subscription; private settingsButtonSub: Subscription;
private captionsSubs: Subscription; private captionsSubs: Subscription;
private additionalButtonsPositionSub: Subscription;
private fullscreenChangeSubscription: Subscription; private fullscreenChangeSubscription: Subscription;
private currentWindowHeight = window.innerHeight; private currentWindowHeight = window.innerHeight;
@ -427,6 +434,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe(); if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe();
if (this.captionsSubs) this.captionsSubs.unsubscribe(); if (this.captionsSubs) this.captionsSubs.unsubscribe();
if (this.fullscreenChangeSubscription) this.fullscreenChangeSubscription.unsubscribe(); if (this.fullscreenChangeSubscription) this.fullscreenChangeSubscription.unsubscribe();
if (this.additionalButtonsPositionSub) this.additionalButtonsPositionSub.unsubscribe();
this.isFullscreenActive = false; this.isFullscreenActive = false;
this.cdkOverlayService.setSelector('body'); this.cdkOverlayService.setSelector('body');
} }
@ -744,6 +752,20 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
this.showCaptionsButton = value; this.showCaptionsButton = value;
this.cd.markForCheck(); this.cd.markForCheck();
}); });
this.additionalButtonsPositionSub = this.libService.toolbarAdditionalButtonsPosition$.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.
// Without this, Angular's OnPush strategy might not immediately reflect the change,
// due to asynchronous operations affecting the timing of the detection cycle.
Promise.resolve().then(() => {
this.additionalButtonsPosition = value;
this.cd.markForCheck();
});
}
);
} }
private subscribeToCaptionsToggling() { private subscribeToCaptionsToggling() {

View File

@ -21,7 +21,8 @@ import {
ToolbarParticipantsPanelButtonDirective, ToolbarParticipantsPanelButtonDirective,
ToolbarRecordingButtonDirective, ToolbarRecordingButtonDirective,
ToolbarScreenshareButtonDirective, ToolbarScreenshareButtonDirective,
ToolbarSettingsButtonDirective ToolbarSettingsButtonDirective,
ToolbarAdditionalButtonsPossitionDirective
} from './toolbar.directive'; } from './toolbar.directive';
import { import {
AudioEnabledDirective, AudioEnabledDirective,
@ -65,6 +66,7 @@ import {
ToolbarDisplayRoomNameDirective, ToolbarDisplayRoomNameDirective,
ToolbarDisplayLogoDirective, ToolbarDisplayLogoDirective,
ToolbarSettingsButtonDirective, ToolbarSettingsButtonDirective,
ToolbarAdditionalButtonsPossitionDirective,
StreamDisplayParticipantNameDirective, StreamDisplayParticipantNameDirective,
StreamDisplayAudioDetectionDirective, StreamDisplayAudioDetectionDirective,
StreamVideoControlsDirective, StreamVideoControlsDirective,
@ -101,6 +103,7 @@ import {
ToolbarDisplayRoomNameDirective, ToolbarDisplayRoomNameDirective,
ToolbarDisplayLogoDirective, ToolbarDisplayLogoDirective,
ToolbarSettingsButtonDirective, ToolbarSettingsButtonDirective,
ToolbarAdditionalButtonsPossitionDirective,
StreamDisplayParticipantNameDirective, StreamDisplayParticipantNameDirective,
StreamDisplayAudioDetectionDirective, StreamDisplayAudioDetectionDirective,
StreamVideoControlsDirective, StreamVideoControlsDirective,

View File

@ -1,5 +1,6 @@
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core'; import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core';
import { OpenViduComponentsConfigService } from '../../services/config/openvidu-components-angular.config.service'; import { OpenViduComponentsConfigService } from '../../services/config/openvidu-components-angular.config.service';
import { ToolbarAdditionalButtonsPosition } from '../../models/toolbar.model';
/** /**
* The **screenshareButton** directive allows show/hide the screenshare toolbar button. * The **screenshareButton** directive allows show/hide the screenshare toolbar button.
@ -812,3 +813,59 @@ export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
} }
} }
} }
/**
* The **ovToolbarAdditionalButtonsPosition** defines the position where the additional buttons should be inserted.
*
* The possible values are: {@link ToolbarAdditionalButtonsPosition}
* Default: `afterMenu`
*
* It can be used in the any element which contains the structural directive {@link ToolbarAdditionalButtonsDirective}.
*
* @example
* <div *ovToolbarAdditionalButtons [ovToolbarAdditionalButtonsPosition]="'beforeMenu'"></div>
*
*/
@Directive({
selector: '[ovToolbarAdditionalButtonsPosition]'
})
export class ToolbarAdditionalButtonsPossitionDirective implements AfterViewInit, OnDestroy {
/**
* @ignore
*/
@Input() set ovToolbarAdditionalButtonsPosition(value: ToolbarAdditionalButtonsPosition) {
if (!value) return;
if (!Object.values(ToolbarAdditionalButtonsPosition).includes(value)) return;
this.additionalButtonsPosition = value;
this.update(this.additionalButtonsPosition);
}
private additionalButtonsPosition: ToolbarAdditionalButtonsPosition = ToolbarAdditionalButtonsPosition.AFTER_MENU;
/**
* @ignore
*/
constructor(
public elementRef: ElementRef,
private libService: OpenViduComponentsConfigService
) {}
ngAfterViewInit() {
this.update(this.additionalButtonsPosition);
}
ngOnDestroy(): void {
this.clear();
}
private clear() {
this.additionalButtonsPosition = ToolbarAdditionalButtonsPosition.AFTER_MENU;
this.update(ToolbarAdditionalButtonsPosition.AFTER_MENU);
}
private update(value: ToolbarAdditionalButtonsPosition) {
if (this.libService.getToolbarAdditionalButtonsPosition() !== value) {
this.libService.setToolbarAdditionalButtonsPosition(value);
}
}
}

View File

@ -0,0 +1,7 @@
/**
* Enum representing the position of additional buttons in a toolbar.
*/
export enum ToolbarAdditionalButtonsPosition {
BEFORE_MENU = 'beforeMenu',
AFTER_MENU = 'afterMenu'
}

View File

@ -3,6 +3,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
import { OpenViduComponentsConfig, ParticipantFactoryFunction } from '../../config/openvidu-components-angular.config'; import { OpenViduComponentsConfig, ParticipantFactoryFunction } from '../../config/openvidu-components-angular.config';
import { RecordingInfo } from '../../models/recording.model'; import { RecordingInfo } from '../../models/recording.model';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { ToolbarAdditionalButtonsPosition } from '../../models/toolbar.model';
// import { version } from '../../../../package.json'; // import { version } from '../../../../package.json';
@ -60,6 +61,12 @@ export class OpenViduComponentsConfigService {
private displayLogo = <BehaviorSubject<boolean>>new BehaviorSubject(true); private displayLogo = <BehaviorSubject<boolean>>new BehaviorSubject(true);
displayLogo$: Observable<boolean>; displayLogo$: Observable<boolean>;
private toolbarAdditionalButtonsPosition = <BehaviorSubject<ToolbarAdditionalButtonsPosition>>(
new BehaviorSubject(ToolbarAdditionalButtonsPosition.AFTER_MENU)
);
toolbarAdditionalButtonsPosition$: Observable<ToolbarAdditionalButtonsPosition>;
private displayParticipantName = <BehaviorSubject<boolean>>new BehaviorSubject(true); private displayParticipantName = <BehaviorSubject<boolean>>new BehaviorSubject(true);
displayParticipantName$: Observable<boolean>; displayParticipantName$: Observable<boolean>;
private displayAudioDetection = <BehaviorSubject<boolean>>new BehaviorSubject(true); private displayAudioDetection = <BehaviorSubject<boolean>>new BehaviorSubject(true);
@ -114,6 +121,7 @@ export class OpenViduComponentsConfigService {
this.broadcastingButton$ = this.broadcastingButton.asObservable(); this.broadcastingButton$ = this.broadcastingButton.asObservable();
this.toolbarSettingsButton$ = this.toolbarSettingsButton.asObservable(); this.toolbarSettingsButton$ = this.toolbarSettingsButton.asObservable();
this.captionsButton$ = this.captionsButton.asObservable(); this.captionsButton$ = this.captionsButton.asObservable();
this.toolbarAdditionalButtonsPosition$ = this.toolbarAdditionalButtonsPosition.asObservable();
//Stream observables //Stream observables
this.displayParticipantName$ = this.displayParticipantName.asObservable(); this.displayParticipantName$ = this.displayParticipantName.asObservable();
this.displayAudioDetection$ = this.displayAudioDetection.asObservable(); this.displayAudioDetection$ = this.displayAudioDetection.asObservable();
@ -261,6 +269,13 @@ export class OpenViduComponentsConfigService {
showLogo(): boolean { showLogo(): boolean {
return this.displayLogo.getValue(); return this.displayLogo.getValue();
} }
getToolbarAdditionalButtonsPosition(): ToolbarAdditionalButtonsPosition {
return this.toolbarAdditionalButtonsPosition.getValue();
}
setToolbarAdditionalButtonsPosition(toolbarAdditionalButtonsPosition: ToolbarAdditionalButtonsPosition) {
this.toolbarAdditionalButtonsPosition.next(toolbarAdditionalButtonsPosition);
}
setRecordingButton(recordingButton: boolean) { setRecordingButton(recordingButton: boolean) {
this.recordingButton.next(recordingButton); this.recordingButton.next(recordingButton);