From 9918b07f517bb4b75f72ebf36aa54734e8bbb005 Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Mon, 24 Nov 2025 13:38:29 +0100 Subject: [PATCH] ov-components: Add directive for injecting custom menu items into toolbar more options --- .../toolbar-media-buttons.component.html | 5 +++ .../toolbar-media-buttons.component.ts | 18 +++++++++- .../components/toolbar/toolbar.component.html | 7 +++- .../components/toolbar/toolbar.component.ts | 30 ++++++++++++++-- .../videoconference.component.html | 5 +++ .../videoconference.component.ts | 29 +++++++++++++-- .../template/internals.directive.ts | 35 +++++++++++++++++++ ...idu-components-angular.directive.module.ts | 9 +++-- .../template/template-manager.service.ts | 19 ++++++++-- 9 files changed, 145 insertions(+), 12 deletions(-) diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.html b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.html index 25b9fdd0d..f2c3bba7e 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.html +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.html @@ -177,6 +177,11 @@ } + + @if (moreOptionsAdditionalMenuItemsTemplate) { + + } + @if (showSettingsButton) { diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.ts index 144017040..96baae5a1 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component.ts @@ -1,8 +1,9 @@ -import { Component, EventEmitter, Input, Output, TemplateRef, computed, inject } from '@angular/core'; +import { Component, ContentChild, EventEmitter, Input, Output, TemplateRef, computed, inject } from '@angular/core'; import { RecordingStatus } from '../../../models/recording.model'; import { BroadcastingStatus } from '../../../models/broadcasting.model'; import { ToolbarAdditionalButtonsPosition } from '../../../models/toolbar.model'; import { ViewportService } from '../../../services/viewport/viewport.service'; +import { ToolbarMoreOptionsAdditionalMenuItemsDirective } from '../../../directives/template/internals.directive'; /** * @internal @@ -71,6 +72,21 @@ export class ToolbarMediaButtonsComponent { // Leave button template @Input() toolbarLeaveButtonTemplate: TemplateRef | null = null; + /** + * @internal + * ContentChild for custom menu items in more options menu + */ + @ContentChild(ToolbarMoreOptionsAdditionalMenuItemsDirective) + externalMoreOptionsAdditionalMenuItems!: ToolbarMoreOptionsAdditionalMenuItemsDirective; + + /** + * @internal + * Gets the template for additional menu items in more options + */ + get moreOptionsAdditionalMenuItemsTemplate(): TemplateRef | undefined { + return this.externalMoreOptionsAdditionalMenuItems?.template; + } + // Status enums for template usage _recordingStatus = RecordingStatus; _broadcastingStatus = BroadcastingStatus; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.html b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.html index ea8d3b84f..cdbe146fc 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.html +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/toolbar/toolbar.component.html @@ -82,7 +82,12 @@ (captionsToggled)="onCaptionsToggle()" (settingsToggled)="toggleSettings()" (leaveClicked)="disconnect()" - > + > + + + + + 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 d9c0382e7..8673b5825 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 @@ -50,7 +50,7 @@ import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.servic import { ParticipantLeftEvent, ParticipantLeftReason, ParticipantModel } from '../../models/participant.model'; import { Room, RoomEvent } from 'livekit-client'; import { ToolbarAdditionalButtonsPosition } from '../../models/toolbar.model'; -import { LeaveButtonDirective } from '../../directives/template/internals.directive'; +import { LeaveButtonDirective, ToolbarMoreOptionsAdditionalMenuItemsDirective } from '../../directives/template/internals.directive'; /** * The **ToolbarComponent** is hosted inside of the {@link VideoconferenceComponent}. @@ -80,6 +80,28 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { | TemplateRef | undefined; + /** + * @internal + * Template for additional menu items in the more options menu + */ + moreOptionsAdditionalMenuItemsTemplate: TemplateRef | undefined; + + private _externalMoreOptionsAdditionalMenuItems?: ToolbarMoreOptionsAdditionalMenuItemsDirective; + /** + * @internal + */ + @ContentChild(ToolbarMoreOptionsAdditionalMenuItemsDirective) + set externalMoreOptionsAdditionalMenuItems(value: ToolbarMoreOptionsAdditionalMenuItemsDirective) { + this._externalMoreOptionsAdditionalMenuItems = value; + this.setupTemplates(); + } + /** + * @internal + */ + get externalMoreOptionsAdditionalMenuItems(): ToolbarMoreOptionsAdditionalMenuItemsDirective | undefined { + return this._externalMoreOptionsAdditionalMenuItems; + } + /** * @ignore */ @@ -494,7 +516,8 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { this.templateConfig = this.templateManagerService.setupToolbarTemplates( this._externalAdditionalButtons, this._externalAdditionalPanelButtons, - this._externalLeaveButton + this._externalLeaveButton, + this._externalMoreOptionsAdditionalMenuItems ); // Apply templates to component properties for backward compatibility @@ -515,6 +538,9 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { if (this.templateConfig.toolbarLeaveButtonTemplate) { this.toolbarLeaveButtonTemplate = this.templateConfig.toolbarLeaveButtonTemplate; } + if (this.templateConfig.toolbarMoreOptionsAdditionalMenuItemsTemplate) { + this.moreOptionsAdditionalMenuItemsTemplate = this.templateConfig.toolbarMoreOptionsAdditionalMenuItemsTemplate; + } } /** diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.html b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.html index 55f5ca2a8..0a64f08ef 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.html +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/videoconference/videoconference.component.html @@ -96,6 +96,11 @@ + + + + + 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 73e15d4ae..5e20e5e53 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 @@ -63,7 +63,8 @@ import { ParticipantPanelAfterLocalParticipantDirective, PreJoinDirective, LeaveButtonDirective, - SettingsPanelGeneralAdditionalElementsDirective + SettingsPanelGeneralAdditionalElementsDirective, + ToolbarMoreOptionsAdditionalMenuItemsDirective } from '../../directives/template/internals.directive'; import { OpenViduThemeService } from '../../services/theme/theme.service'; import { E2eeService } from '../../services/e2ee/e2ee.service'; @@ -392,6 +393,22 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { return this._externalSettingsPanelGeneralAdditionalElements; } + private _externalToolbarMoreOptionsAdditionalMenuItems?: ToolbarMoreOptionsAdditionalMenuItemsDirective; + /** + * @internal + */ + @ContentChild(ToolbarMoreOptionsAdditionalMenuItemsDirective) + set externalToolbarMoreOptionsAdditionalMenuItems(value: ToolbarMoreOptionsAdditionalMenuItemsDirective) { + this._externalToolbarMoreOptionsAdditionalMenuItems = value; + this.setupTemplates(); + } + /** + * @internal + */ + get externalToolbarMoreOptionsAdditionalMenuItems(): ToolbarMoreOptionsAdditionalMenuItemsDirective | undefined { + return this._externalToolbarMoreOptionsAdditionalMenuItems; + } + /** * @internal */ @@ -498,6 +515,10 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { * @internal */ ovSettingsPanelGeneralAdditionalElementsTemplate: TemplateRef; + /** + * @internal + */ + ovToolbarMoreOptionsAdditionalMenuItemsTemplate: TemplateRef; /** * @internal @@ -808,7 +829,8 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { stream: this.externalStream, preJoin: this.externalPreJoin, layoutAdditionalElements: this.externalLayoutAdditionalElements, - settingsPanelGeneralAdditionalElements: this.externalSettingsPanelGeneralAdditionalElements + settingsPanelGeneralAdditionalElements: this.externalSettingsPanelGeneralAdditionalElements, + toolbarMoreOptionsAdditionalMenuItems: this.externalToolbarMoreOptionsAdditionalMenuItems }; const defaultTemplates: DefaultTemplates = { @@ -886,6 +908,9 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit { if (this.templateConfig.settingsPanelGeneralAdditionalElementsTemplate) { assignIfChanged('ovSettingsPanelGeneralAdditionalElementsTemplate', this.templateConfig.settingsPanelGeneralAdditionalElementsTemplate); } + if (this.templateConfig.toolbarMoreOptionsAdditionalMenuItemsTemplate) { + assignIfChanged('ovToolbarMoreOptionsAdditionalMenuItemsTemplate', this.templateConfig.toolbarMoreOptionsAdditionalMenuItemsTemplate); + } } /** diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/internals.directive.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/internals.directive.ts index e5314fbdc..0b8999e31 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/internals.directive.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/internals.directive.ts @@ -343,3 +343,38 @@ export class SettingsPanelGeneralAdditionalElementsDirective { public container: ViewContainerRef ) {} } + +/** + * The ***ovToolbarMoreOptionsAdditionalMenuItems** directive allows you to inject custom HTML or Angular templates + * into the "more options" menu (three dots button) of the toolbar. + * This enables you to add custom menu items to extend the toolbar functionality. + * + * Usage example: + * ```html + * + * + * + * + * + * + * + * ``` + * + * @internal + */ +@Directive({ + selector: '[ovToolbarMoreOptionsAdditionalMenuItems]', + standalone: false +}) +export class ToolbarMoreOptionsAdditionalMenuItemsDirective { + constructor( + public template: TemplateRef, + public container: ViewContainerRef + ) {} +} \ No newline at end of file diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/openvidu-components-angular.directive.module.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/openvidu-components-angular.directive.module.ts index c7496309f..436a20783 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/openvidu-components-angular.directive.module.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/directives/template/openvidu-components-angular.directive.module.ts @@ -20,7 +20,8 @@ import { ParticipantPanelParticipantBadgeDirective, PreJoinDirective, LeaveButtonDirective, - SettingsPanelGeneralAdditionalElementsDirective + SettingsPanelGeneralAdditionalElementsDirective, + ToolbarMoreOptionsAdditionalMenuItemsDirective } from './internals.directive'; @NgModule({ @@ -42,7 +43,8 @@ import { ParticipantPanelAfterLocalParticipantDirective, LayoutAdditionalElementsDirective, ParticipantPanelParticipantBadgeDirective, - SettingsPanelGeneralAdditionalElementsDirective + SettingsPanelGeneralAdditionalElementsDirective, + ToolbarMoreOptionsAdditionalMenuItemsDirective // BackgroundEffectsPanelDirective ], exports: [ @@ -63,7 +65,8 @@ import { ParticipantPanelAfterLocalParticipantDirective, LayoutAdditionalElementsDirective, ParticipantPanelParticipantBadgeDirective, - SettingsPanelGeneralAdditionalElementsDirective + SettingsPanelGeneralAdditionalElementsDirective, + ToolbarMoreOptionsAdditionalMenuItemsDirective // BackgroundEffectsPanelDirective ] }) diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/template/template-manager.service.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/template/template-manager.service.ts index d0d3df252..f3cbf2b00 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/template/template-manager.service.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/template/template-manager.service.ts @@ -20,7 +20,8 @@ import { ParticipantPanelAfterLocalParticipantDirective, LayoutAdditionalElementsDirective, LeaveButtonDirective, - SettingsPanelGeneralAdditionalElementsDirective + SettingsPanelGeneralAdditionalElementsDirective, + ToolbarMoreOptionsAdditionalMenuItemsDirective } from '../../directives/template/internals.directive'; /** @@ -53,6 +54,9 @@ export interface TemplateConfiguration { // Settings panel templates settingsPanelGeneralAdditionalElementsTemplate?: TemplateRef; + // Toolbar templates + toolbarMoreOptionsAdditionalMenuItemsTemplate?: TemplateRef; + // PreJoin template preJoinTemplate?: TemplateRef; } @@ -76,6 +80,7 @@ export interface ToolbarTemplateConfiguration { toolbarAdditionalButtonsTemplate?: TemplateRef; toolbarAdditionalPanelButtonsTemplate?: TemplateRef; toolbarLeaveButtonTemplate?: TemplateRef; + toolbarMoreOptionsAdditionalMenuItemsTemplate?: TemplateRef; } /** @@ -131,6 +136,7 @@ export interface ExternalDirectives { preJoin?: PreJoinDirective; layoutAdditionalElements?: LayoutAdditionalElementsDirective; settingsPanelGeneralAdditionalElements?: SettingsPanelGeneralAdditionalElementsDirective; + toolbarMoreOptionsAdditionalMenuItems?: ToolbarMoreOptionsAdditionalMenuItemsDirective; } /** @@ -218,6 +224,11 @@ export class TemplateManagerService { config.settingsPanelGeneralAdditionalElementsTemplate = externalDirectives.settingsPanelGeneralAdditionalElements.template; } + if (externalDirectives.toolbarMoreOptionsAdditionalMenuItems) { + this.log.v('Setting EXTERNAL TOOLBAR MORE OPTIONS ADDITIONAL MENU ITEMS'); + config.toolbarMoreOptionsAdditionalMenuItemsTemplate = externalDirectives.toolbarMoreOptionsAdditionalMenuItems.template; + } + this.log.v('Template setup completed', config); return config; } @@ -378,14 +389,16 @@ export class TemplateManagerService { setupToolbarTemplates( externalAdditionalButtons?: ToolbarAdditionalButtonsDirective, externalAdditionalPanelButtons?: ToolbarAdditionalPanelButtonsDirective, - externalLeaveButton?: LeaveButtonDirective + externalLeaveButton?: LeaveButtonDirective, + externalMoreOptionsAdditionalMenuItems?: ToolbarMoreOptionsAdditionalMenuItemsDirective ): ToolbarTemplateConfiguration { this.log.v('Setting up toolbar templates...'); return { toolbarAdditionalButtonsTemplate: externalAdditionalButtons?.template, toolbarAdditionalPanelButtonsTemplate: externalAdditionalPanelButtons?.template, - toolbarLeaveButtonTemplate: externalLeaveButton?.template + toolbarLeaveButtonTemplate: externalLeaveButton?.template, + toolbarMoreOptionsAdditionalMenuItemsTemplate: externalMoreOptionsAdditionalMenuItems?.template }; }