ov-components: enhance layout flexibility with additional element slots and improved rendering logic

master
Carlos Santos 2025-12-22 16:55:57 +01:00
parent ff492a1f22
commit 3c02121ebe
7 changed files with 171 additions and 152 deletions

View File

@ -1,5 +1,10 @@
<div class="container" [ngClass]="{ withCaptions: captionsEnabled, withMargin: localParticipant.isMinimized }"> <div class="container" [ngClass]="{ withCaptions: captionsEnabled, withMargin: localParticipant.isMinimized }">
<div id="layout" class="layout" #layout> <div id="layout" class="layout" #layout>
<!-- Top slot: Render elements that should appear at the top -->
@if (layoutAdditionalElementsTemplate && templateConfig.layoutAdditionalElementsSlot === 'top') {
<ng-container *ngTemplateOutlet="layoutAdditionalElementsTemplate"></ng-container>
}
<div <div
#localLayoutElement #localLayoutElement
*ngFor="let track of localParticipant.tracks; trackBy: trackParticipantElement" *ngFor="let track of localParticipant.tracks; trackBy: trackParticipantElement"
@ -21,8 +26,8 @@
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: track }"></ng-container> <ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: track }"></ng-container>
</div> </div>
<!-- Render additional layout elements injected via ovAdditionalLayoutElement --> <!-- Default slot: Render additional layout elements (backward compatibility and default position) -->
@if (layoutAdditionalElementsTemplate) { @if (layoutAdditionalElementsTemplate && (templateConfig.layoutAdditionalElementsSlot === 'default' || !templateConfig.layoutAdditionalElementsSlot)) {
<ng-container *ngTemplateOutlet="layoutAdditionalElementsTemplate"></ng-container> <ng-container *ngTemplateOutlet="layoutAdditionalElementsTemplate"></ng-container>
} }
@ -40,6 +45,11 @@
> >
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: track }"></ng-container> <ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: track }"></ng-container>
</div> </div>
<!-- Bottom slot: Render elements that should appear at the bottom -->
@if (layoutAdditionalElementsTemplate && templateConfig.layoutAdditionalElementsSlot === 'bottom') {
<ng-container *ngTemplateOutlet="layoutAdditionalElementsTemplate"></ng-container>
}
</div> </div>
<!-- <ov-captions *ngIf="captionsEnabled" class="OV_ignored"></ov-captions> --> <!-- <ov-captions *ngIf="captionsEnabled" class="OV_ignored"></ov-captions> -->

View File

@ -1,5 +1,6 @@
import { LayoutAdditionalElementsDirective } from '../../directives/template/internals.directive'; import { LayoutAdditionalElementsDirective } from '../../directives/template/internals.directive';
import { CdkDrag } from '@angular/cdk/drag-drop';
import { import {
AfterViewInit, AfterViewInit,
ChangeDetectionStrategy, ChangeDetectionStrategy,
@ -15,13 +16,12 @@ import {
} from '@angular/core'; } from '@angular/core';
import { combineLatest, map, Subject, takeUntil } from 'rxjs'; import { combineLatest, map, Subject, takeUntil } from 'rxjs';
import { StreamDirective } from '../../directives/template/openvidu-components-angular.directive'; import { StreamDirective } from '../../directives/template/openvidu-components-angular.directive';
import { ParticipantTrackPublication, ParticipantModel } from '../../models/participant.model'; import { ParticipantModel, ParticipantTrackPublication } from '../../models/participant.model';
import { LayoutService } from '../../services/layout/layout.service';
import { ParticipantService } from '../../services/participant/participant.service';
import { CdkDrag } from '@angular/cdk/drag-drop';
import { PanelService } from '../../services/panel/panel.service';
import { GlobalConfigService } from '../../services/config/global-config.service';
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service'; import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
import { GlobalConfigService } from '../../services/config/global-config.service';
import { LayoutService } from '../../services/layout/layout.service';
import { PanelService } from '../../services/panel/panel.service';
import { ParticipantService } from '../../services/participant/participant.service';
import { LayoutTemplateConfiguration, TemplateManagerService } from '../../services/template/template-manager.service'; import { LayoutTemplateConfiguration, TemplateManagerService } from '../../services/template/template-manager.service';
/** /**

View File

@ -181,7 +181,7 @@
* @internal * @internal
*/ */
import { Directive, TemplateRef, ViewContainerRef } from '@angular/core'; import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ @Directive({
selector: '[ovPreJoin]', selector: '[ovPreJoin]',
@ -253,14 +253,27 @@ export class LeaveButtonDirective {
* as additional layout elements within the videoconference UI. * as additional layout elements within the videoconference UI.
* This enables you to extend the layout with extra controls, banners, or any custom UI. * This enables you to extend the layout with extra controls, banners, or any custom UI.
* *
* Usage example: * You can specify a slot to control where the element is positioned:
* - 'top': Position at the top of the layout (after local participant, before remote participants)
* - 'bottom': Position at the bottom of the layout (after all participants)
* - 'default' or no slot: Position after local participant (default behavior)
*
* Usage examples:
* ```html * ```html
* <ov-videoconference> * <ov-videoconference>
* <!-- Default position (after local participant) -->
* <ng-container *ovLayoutAdditionalElements> * <ng-container *ovLayoutAdditionalElements>
* <div class="my-custom-layout-element"> * <div class="my-banner">Banner</div>
* <!-- Your custom HTML here --> * </ng-container>
* <span>Extra layout element</span> *
* </div> * <!-- Top position -->
* <ng-container *ovLayoutAdditionalElements="'top'">
* <div class="top-bar">Top Bar</div>
* </ng-container>
*
* <!-- Bottom position -->
* <ng-container *ovLayoutAdditionalElements="'bottom'">
* <div class="bottom-info">Footer Info</div>
* </ng-container> * </ng-container>
* </ov-videoconference> * </ov-videoconference>
* ``` * ```
@ -270,10 +283,27 @@ export class LeaveButtonDirective {
standalone: false standalone: false
}) })
export class LayoutAdditionalElementsDirective { export class LayoutAdditionalElementsDirective {
/**
* Slot position: 'top', 'bottom', or 'default'
*/
slot: 'top' | 'bottom' | 'default' = 'default';
constructor( constructor(
public template: TemplateRef<any>, public template: TemplateRef<any>,
public container: ViewContainerRef public container: ViewContainerRef
) {} ) {}
/**
* @ignore
*/
@Input('ovLayoutAdditionalElements')
set ovLayoutAdditionalElements(slot: 'top' | 'bottom' | 'default' | '') {
if (slot === 'top' || slot === 'bottom' || slot === 'default') {
this.slot = slot;
} else {
this.slot = 'default';
}
}
} }
/** /**

View File

@ -5,6 +5,7 @@ export enum LayoutClass {
ROOT_ELEMENT = 'OV_root', ROOT_ELEMENT = 'OV_root',
BIG_ELEMENT = 'OV_big', BIG_ELEMENT = 'OV_big',
SMALL_ELEMENT = 'OV_small', SMALL_ELEMENT = 'OV_small',
TOP_BAR_ELEMENT = 'OV_top-bar',
IGNORED_ELEMENT = 'OV_ignored', IGNORED_ELEMENT = 'OV_ignored',
MINIMIZED_ELEMENT = 'OV_minimized', MINIMIZED_ELEMENT = 'OV_minimized',
SIDENAV_CONTAINER = 'sidenav-container', SIDENAV_CONTAINER = 'sidenav-container',
@ -42,6 +43,7 @@ export interface ElementDimensions {
width: number; width: number;
big?: boolean; big?: boolean;
small?: boolean; small?: boolean;
topBar?: boolean;
} }
/** /**
@ -200,7 +202,8 @@ export class OpenViduLayout {
const elements = children.map((element) => { const elements = children.map((element) => {
const res = this.getChildDims(element); const res = this.getChildDims(element);
res.big = element.classList.contains(this.opts.bigClass); res.big = element.classList.contains(this.opts.bigClass);
res.small = element.classList.contains(this.opts.smallClass); res.small = element.classList.contains(LayoutClass.SMALL_ELEMENT);
res.topBar = element.classList.contains(LayoutClass.TOP_BAR_ELEMENT);
return res; return res;
}); });
@ -545,13 +548,15 @@ export class OpenViduLayout {
let bigOffsetLeft = 0; let bigOffsetLeft = 0;
const bigIndices: number[] = []; const bigIndices: number[] = [];
const smallIndices: number[] = []; const smallIndices: number[] = [];
const topBarIndices: number[] = [];
const normalIndices: number[] = []; const normalIndices: number[] = [];
let bigBoxes: LayoutBox[] = []; let bigBoxes: LayoutBox[] = [];
let smallBoxes: LayoutBox[] = []; let smallBoxes: LayoutBox[] = [];
let topBarBoxes: LayoutBox[] = [];
let normalBoxes: LayoutBox[] = []; let normalBoxes: LayoutBox[] = [];
let areas: { big: LayoutArea | null; normal: LayoutArea | null; small: LayoutArea | null } = { big: null, normal: null, small: null }; let areas: { big: LayoutArea | null; normal: LayoutArea | null; small: LayoutArea | null; topBar: LayoutArea | null } = { big: null, normal: null, small: null, topBar: null };
// Separate elements into three categories: big, small, and normal // Separate elements into categories: big, small, topbar, and normal
const bigOnes = elements.filter((element, idx) => { const bigOnes = elements.filter((element, idx) => {
if (element.big) { if (element.big) {
bigIndices.push(idx); bigIndices.push(idx);
@ -559,23 +564,31 @@ export class OpenViduLayout {
} }
return false; return false;
}); });
const topBarOnes = elements.filter((element, idx) => {
if (!element.big && element.topBar) {
topBarIndices.push(idx);
return true;
}
return false;
});
const smallOnes = elements.filter((element, idx) => { const smallOnes = elements.filter((element, idx) => {
if (!element.big && element.small) { if (!element.big && !element.topBar && element.small) {
smallIndices.push(idx); smallIndices.push(idx);
return true; return true;
} }
return false; return false;
}); });
const normalOnes = elements.filter((element, idx) => { const normalOnes = elements.filter((element, idx) => {
if (!element.big && !element.small) { if (!element.big && !element.topBar && !element.small) {
normalIndices.push(idx); normalIndices.push(idx);
return true; return true;
} }
return false; return false;
}); });
// Handle different layout scenarios based on element types // Handle different layout scenarios based on element types
if (bigOnes.length > 0 && (normalOnes.length > 0 || smallOnes.length > 0)) { if (bigOnes.length > 0 && (normalOnes.length > 0 || smallOnes.length > 0 || topBarOnes.length > 0)) {
// Scenario: Big elements with normal/small elements // Scenario: Big elements with normal/small/topbar elements
let bigWidth; let bigWidth;
let bigHeight; let bigHeight;
let showBigFirst = bigFirst; let showBigFirst = bigFirst;
@ -622,7 +635,7 @@ export class OpenViduLayout {
maxRatio, maxRatio,
containerWidth, containerWidth,
containerHeight - bigHeight, containerHeight - bigHeight,
normalOnes.length + smallOnes.length, normalOnes.length + smallOnes.length + topBarOnes.length,
smallMaxWidth, smallMaxWidth,
smallMaxHeight smallMaxHeight
); );
@ -677,7 +690,7 @@ export class OpenViduLayout {
maxRatio, maxRatio,
containerWidth - bigWidth, containerWidth - bigWidth,
containerHeight, containerHeight,
normalOnes.length + smallOnes.length, normalOnes.length + smallOnes.length + topBarOnes.length,
smallMaxWidth, smallMaxWidth,
smallMaxHeight smallMaxHeight
); );
@ -718,16 +731,16 @@ export class OpenViduLayout {
height: containerHeight - offsetTop height: containerHeight - offsetTop
}; };
} }
} else if (bigOnes.length > 0 && smallOnes.length === 0) { } else if (bigOnes.length > 0 && normalOnes.length === 0 && smallOnes.length === 0 && topBarOnes.length === 0) {
// We only have one bigOne just center it // We only have bigOnes just center it
areas.big = { areas.big = {
top: 0, top: 0,
left: 0, left: 0,
width: containerWidth, width: containerWidth,
height: containerHeight height: containerHeight
}; };
} else if (normalOnes.length > 0 || smallOnes.length > 0) { } else if (normalOnes.length > 0 || smallOnes.length > 0 || topBarOnes.length > 0) {
// Only normal and/or small elements // Only normal, small, and/or topbar elements
areas.normal = { areas.normal = {
top: offsetTop, top: offsetTop,
left: offsetLeft, left: offsetLeft,
@ -755,75 +768,67 @@ export class OpenViduLayout {
); );
} }
if (areas.normal) { if (areas.normal) {
// Calculate equivalent "normal-sized" count considering small elements take less space let currentTop = areas.normal.top;
// Treat each small element as taking up a fraction of a normal element's space let remainingHeight = areas.normal.height;
const smallElementSpaceFactor = 0.25; // Small elements take ~25% of normal element space
const equivalentNormalCount = normalOnes.length + (smallOnes.length * smallElementSpaceFactor);
// Calculate layout for all elements together as if they were normal-sized // 1. Position TopBar Elements at the very top (header style: full width, 80px height)
const allNormalAreaElements = [...normalOnes, ...smallOnes]; if (topBarOnes.length > 0) {
const topBarHeight = 80;
const topBarWidth = Math.floor(containerWidth / topBarOnes.length);
if (allNormalAreaElements.length > 0) { topBarBoxes = topBarOnes.map((element, idx) => {
// Get dimensions as if all elements were normal-sized
const allBoxes = this.getLayoutAux(
{
containerWidth: areas.normal.width,
containerHeight: areas.normal.height,
offsetLeft: areas.normal.left,
offsetTop: areas.normal.top,
fixedRatio,
minRatio,
maxRatio,
alignItems: areas.big ? smallAlignItems : alignItems,
maxWidth: areas.big ? maxWidth : maxWidth,
maxHeight: areas.big ? maxHeight : maxHeight,
scaleLastRow
},
allNormalAreaElements
);
// Split boxes and adjust small elements
normalBoxes = allBoxes.slice(0, normalOnes.length);
const rawSmallBoxes = allBoxes.slice(normalOnes.length);
// Adjust small element boxes to use restricted dimensions and reposition them
// to utilize space efficiently
smallBoxes = rawSmallBoxes.map((box, idx) => {
// Calculate restricted size while maintaining aspect ratio
const restrictedWidth = Math.min(box.width, smallMaxWidth);
const restrictedHeight = Math.min(box.height, smallMaxHeight);
// Maintain the position but adjust size
return { return {
left: box.left, left: areas.normal!.left + idx * topBarWidth,
top: box.top, top: currentTop,
width: restrictedWidth, width: topBarWidth,
height: restrictedHeight height: topBarHeight
}; };
}); });
// If there are small elements, try to compact them and redistribute space currentTop += topBarHeight;
if (smallOnes.length > 0 && normalOnes.length > 0) { remainingHeight -= topBarHeight;
// Recalculate normal elements with more space since small elements take less }
const adjustedDimensions = this.getBestDimensions(
minRatio,
maxRatio,
areas.normal.width,
areas.normal.height,
equivalentNormalCount,
areas.big ? maxWidth : maxWidth,
areas.big ? maxHeight : maxHeight
);
// If the adjusted dimensions give us bigger normal elements, recalculate // 2. Position Small Elements (reduced format)
if (normalBoxes.length > 0 && if (smallOnes.length > 0) {
adjustedDimensions.targetHeight > normalBoxes[0].height) { const maxSmallWidthAvailable = smallMaxWidth;
const maxSmallHeightAvailable = smallMaxHeight;
const tentativeCols = maxSmallWidthAvailable === Infinity
? smallOnes.length
: Math.max(1, Math.floor(containerWidth / maxSmallWidthAvailable));
const displayCols = Math.max(1, Math.min(smallOnes.length, tentativeCols));
const computedWidth = maxSmallWidthAvailable === Infinity
? Math.floor(containerWidth / displayCols)
: maxSmallWidthAvailable;
const computedHeight = maxSmallHeightAvailable === Infinity ? computedWidth : maxSmallHeightAvailable;
const rowWidth = displayCols * computedWidth;
const rowOffset = Math.floor(Math.max(0, containerWidth - rowWidth) / 2);
smallBoxes = smallOnes.map((element, idx) => {
const col = idx % displayCols;
return {
left: areas.normal!.left + col * computedWidth + rowOffset,
top: currentTop,
width: computedWidth,
height: computedHeight
};
});
currentTop += computedHeight;
remainingHeight -= computedHeight;
}
// 3. Position Normal Elements in remaining space
if (normalOnes.length > 0) {
normalBoxes = this.getLayoutAux( normalBoxes = this.getLayoutAux(
{ {
containerWidth: areas.normal.width, containerWidth: areas.normal.width,
containerHeight: areas.normal.height, containerHeight: Math.max(0, remainingHeight),
offsetLeft: areas.normal.left, offsetLeft: areas.normal.left,
offsetTop: areas.normal.top, offsetTop: currentTop,
fixedRatio, fixedRatio,
minRatio, minRatio,
maxRatio, maxRatio,
@ -834,42 +839,6 @@ export class OpenViduLayout {
}, },
normalOnes normalOnes
); );
// Position small elements in remaining space (bottom or side)
const normalMaxBottom = normalBoxes.length > 0 ? Math.max(...normalBoxes.map(b => b.top + b.height)) : areas.normal.top;
const normalMaxRight = normalBoxes.length > 0 ? Math.max(...normalBoxes.map(b => b.left + b.width)) : areas.normal.left;
// Position small elements at the end of the layout
const spaceAtBottom = (areas.normal.top + areas.normal.height) - normalMaxBottom;
const spaceAtRight = (areas.normal.left + areas.normal.width) - normalMaxRight;
let smallStartX = areas.normal.left;
let smallStartY = normalMaxBottom;
let availableWidth = areas.normal.width;
// Choose best positioning based on available space
if (spaceAtBottom < smallMaxHeight && spaceAtRight >= smallMaxWidth) {
// Position to the right
smallStartX = normalMaxRight;
smallStartY = areas.normal.top;
availableWidth = spaceAtRight;
}
// Arrange small elements in a compact grid
const smallCols = Math.floor(availableWidth / smallMaxWidth);
smallBoxes = smallOnes.map((_, idx) => {
const col = idx % Math.max(1, smallCols);
const row = Math.floor(idx / Math.max(1, smallCols));
return {
left: smallStartX + (col * smallMaxWidth),
top: smallStartY + (row * smallMaxHeight),
width: smallMaxWidth,
height: smallMaxHeight
};
});
}
}
} }
} }
@ -877,15 +846,22 @@ export class OpenViduLayout {
let bigBoxesIdx = 0; let bigBoxesIdx = 0;
let normalBoxesIdx = 0; let normalBoxesIdx = 0;
let smallBoxesIdx = 0; let smallBoxesIdx = 0;
let topBarBoxesIdx = 0;
// Rebuild the array in the right order based on element types // Rebuild the array in the right order based on element types
elements.forEach((element, idx) => { elements.forEach((element, idx) => {
if (bigIndices.indexOf(idx) > -1) { if (bigIndices.indexOf(idx) > -1) {
boxes[idx] = bigBoxes[bigBoxesIdx]; boxes[idx] = bigBoxes[bigBoxesIdx];
bigBoxesIdx += 1; bigBoxesIdx += 1;
} else if (topBarIndices.indexOf(idx) > -1) {
// Element is topbar (header style: full width, limited height)
boxes[idx] = topBarBoxes[topBarBoxesIdx];
topBarBoxesIdx += 1;
} else if (smallIndices.indexOf(idx) > -1) { } else if (smallIndices.indexOf(idx) > -1) {
// Element is small (reduced format)
boxes[idx] = smallBoxes[smallBoxesIdx]; boxes[idx] = smallBoxes[smallBoxesIdx];
smallBoxesIdx += 1; smallBoxesIdx += 1;
} else { } else {
// Element is normal
boxes[idx] = normalBoxes[normalBoxesIdx]; boxes[idx] = normalBoxes[normalBoxesIdx];
normalBoxesIdx += 1; normalBoxesIdx += 1;
} }

View File

@ -101,7 +101,7 @@ export class LayoutService {
maxWidth: Infinity, maxWidth: Infinity,
maxHeight: Infinity, maxHeight: Infinity,
smallMaxWidth: Infinity, smallMaxWidth: Infinity,
smallMaxHeight: Infinity, smallMaxHeight: 80,
bigMaxWidth: Infinity, bigMaxWidth: Infinity,
bigMaxHeight: Infinity, bigMaxHeight: Infinity,
scaleLastRow: true, scaleLastRow: true,

View File

@ -1,6 +1,12 @@
import { Injectable, TemplateRef } from '@angular/core'; import { Injectable, TemplateRef } from '@angular/core';
import { ILogger } from '../../models/logger.model'; import {
import { LoggerService } from '../logger/logger.service'; LayoutAdditionalElementsDirective,
LeaveButtonDirective,
ParticipantPanelAfterLocalParticipantDirective,
PreJoinDirective,
SettingsPanelGeneralAdditionalElementsDirective,
ToolbarMoreOptionsAdditionalMenuItemsDirective
} from '../../directives/template/internals.directive';
import { import {
ActivitiesPanelDirective, ActivitiesPanelDirective,
AdditionalPanelsDirective, AdditionalPanelsDirective,
@ -15,14 +21,8 @@ import {
ToolbarAdditionalPanelButtonsDirective, ToolbarAdditionalPanelButtonsDirective,
ToolbarDirective ToolbarDirective
} from '../../directives/template/openvidu-components-angular.directive'; } from '../../directives/template/openvidu-components-angular.directive';
import { import { ILogger } from '../../models/logger.model';
PreJoinDirective, import { LoggerService } from '../logger/logger.service';
ParticipantPanelAfterLocalParticipantDirective,
LayoutAdditionalElementsDirective,
LeaveButtonDirective,
SettingsPanelGeneralAdditionalElementsDirective,
ToolbarMoreOptionsAdditionalMenuItemsDirective
} from '../../directives/template/internals.directive';
/** /**
* Configuration object for all templates in the videoconference component * Configuration object for all templates in the videoconference component
@ -89,6 +89,7 @@ export interface ToolbarTemplateConfiguration {
export interface LayoutTemplateConfiguration { export interface LayoutTemplateConfiguration {
layoutStreamTemplate?: TemplateRef<any>; layoutStreamTemplate?: TemplateRef<any>;
layoutAdditionalElementsTemplate?: TemplateRef<any>; layoutAdditionalElementsTemplate?: TemplateRef<any>;
layoutAdditionalElementsSlot?: 'top' | 'bottom' | 'default';
} }
/** /**
@ -413,7 +414,8 @@ export class TemplateManagerService {
return { return {
layoutStreamTemplate: externalStream?.template, layoutStreamTemplate: externalStream?.template,
layoutAdditionalElementsTemplate: externalLayoutAdditionalElements?.template layoutAdditionalElementsTemplate: externalLayoutAdditionalElements?.template,
layoutAdditionalElementsSlot: externalLayoutAdditionalElements?.slot || 'default'
}; };
} }

View File

@ -5,6 +5,7 @@
// Components // Components
export * from './lib/admin/admin-dashboard/admin-dashboard.component'; export * from './lib/admin/admin-dashboard/admin-dashboard.component';
export * from './lib/admin/admin-login/admin-login.component'; export * from './lib/admin/admin-login/admin-login.component';
export * from './lib/components/landscape-warning/landscape-warning.component';
export * from './lib/components/layout/layout.component'; export * from './lib/components/layout/layout.component';
export * from './lib/components/panel/activities-panel/activities-panel.component'; export * from './lib/components/panel/activities-panel/activities-panel.component';
export * from './lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component'; export * from './lib/components/panel/activities-panel/broadcasting-activity/broadcasting-activity.component';
@ -14,11 +15,10 @@ export * from './lib/components/panel/panel.component';
export * from './lib/components/panel/participants-panel/participant-panel-item/participant-panel-item.component'; export * from './lib/components/panel/participants-panel/participant-panel-item/participant-panel-item.component';
export * from './lib/components/panel/participants-panel/participants-panel/participants-panel.component'; export * from './lib/components/panel/participants-panel/participants-panel/participants-panel.component';
export * from './lib/components/stream/stream.component'; export * from './lib/components/stream/stream.component';
export * from './lib/components/toolbar/toolbar.component';
export * from './lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component'; export * from './lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component';
export * from './lib/components/toolbar/toolbar-panel-buttons/toolbar-panel-buttons.component'; export * from './lib/components/toolbar/toolbar-panel-buttons/toolbar-panel-buttons.component';
export * from './lib/components/toolbar/toolbar.component';
export * from './lib/components/videoconference/videoconference.component'; export * from './lib/components/videoconference/videoconference.component';
export * from './lib/components/landscape-warning/landscape-warning.component';
export * from './lib/config/openvidu-components-angular.config'; export * from './lib/config/openvidu-components-angular.config';
// Directives // Directives
export * from './lib/directives/api/activities-panel.directive'; export * from './lib/directives/api/activities-panel.directive';
@ -35,18 +35,19 @@ export * from './lib/directives/template/openvidu-components-angular.directive';
export * from './lib/directives/template/openvidu-components-angular.directive.module'; export * from './lib/directives/template/openvidu-components-angular.directive.module';
// Models // Models
export * from './lib/models/broadcasting.model'; export * from './lib/models/broadcasting.model';
export * from './lib/models/data-topic.model';
export * from './lib/models/device.model';
export * from './lib/models/lang.model';
export * from './lib/models/layout.model';
export * from './lib/models/logger.model';
export * from './lib/models/panel.model'; export * from './lib/models/panel.model';
export * from './lib/models/participant.model'; export * from './lib/models/participant.model';
export * from './lib/models/recording.model'; export * from './lib/models/recording.model';
export * from './lib/models/data-topic.model';
export * from './lib/models/room.model'; export * from './lib/models/room.model';
export * from './lib/models/toolbar.model';
export * from './lib/models/logger.model';
export * from './lib/models/storage.model'; export * from './lib/models/storage.model';
export * from './lib/models/lang.model';
export * from './lib/models/theme.model'; export * from './lib/models/theme.model';
export * from './lib/models/toolbar.model';
export * from './lib/models/viewport.model'; export * from './lib/models/viewport.model';
export * from './lib/models/device.model';
// Pipes // Pipes
export * from './lib/pipes/participant.pipe'; export * from './lib/pipes/participant.pipe';
export * from './lib/pipes/recording.pipe'; export * from './lib/pipes/recording.pipe';
@ -55,21 +56,21 @@ export * from './lib/pipes/translate.pipe';
export * from './lib/services/action/action.service'; export * from './lib/services/action/action.service';
export * from './lib/services/broadcasting/broadcasting.service'; export * from './lib/services/broadcasting/broadcasting.service';
export * from './lib/services/chat/chat.service'; export * from './lib/services/chat/chat.service';
export * from './lib/services/config/global-config.service';
export * from './lib/services/e2ee/e2ee.service';
export * from './lib/services/layout/layout.service'; export * from './lib/services/layout/layout.service';
export * from './lib/services/logger/logger.service';
export * from './lib/services/openvidu/openvidu.service'; export * from './lib/services/openvidu/openvidu.service';
export * from './lib/services/panel/panel.service'; export * from './lib/services/panel/panel.service';
export * from './lib/services/participant/participant.service'; export * from './lib/services/participant/participant.service';
export * from './lib/services/recording/recording.service'; export * from './lib/services/recording/recording.service';
export * from './lib/services/config/global-config.service';
export * from './lib/services/logger/logger.service';
export * from './lib/services/storage/storage.service'; export * from './lib/services/storage/storage.service';
export * from './lib/services/translate/translate.service';
export * from './lib/services/theme/theme.service'; export * from './lib/services/theme/theme.service';
export * from './lib/services/translate/translate.service';
export * from './lib/services/viewport/viewport.service'; export * from './lib/services/viewport/viewport.service';
export * from './lib/services/e2ee/e2ee.service';
//Modules //Modules
export * from './lib/openvidu-components-angular.module';
export * from './lib/config/custom-cdk-overlay'; export * from './lib/config/custom-cdk-overlay';
export * from './lib/openvidu-components-angular-ui.module'; export * from './lib/openvidu-components-angular-ui.module';
export * from './lib/openvidu-components-angular.module';
export * from 'livekit-client'; export * from 'livekit-client';