frontend: add meeting settings panel and more options buttons for layout configuration
This commit is contained in:
parent
b177b3b02e
commit
c8cfb6598e
@ -2,3 +2,5 @@ export * from './meeting-toolbar-buttons/meeting-toolbar-buttons.component';
|
||||
export * from './meeting-share-link-panel/meeting-share-link-panel.component';
|
||||
export * from './meeting-participant-panel-item/meeting-participant-panel-item.component';
|
||||
export * from './meeting-layout/meeting-layout.component';
|
||||
export * from './meeting-settings-panel/meeting-settings-panel.component';
|
||||
export * from './meeting-toolbar-more-options-buttons/meeting-toolbar-more-options-buttons.component';
|
||||
|
||||
@ -92,7 +92,7 @@ describe('MeetingLayoutComponent', () => {
|
||||
describe('Default Layout Mode', () => {
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
layoutModeSubject.next(MeetLayoutMode.DEFAULT);
|
||||
layoutModeSubject.next(MeetLayoutMode.MOSAIC);
|
||||
});
|
||||
|
||||
it('should show all remote participants in DEFAULT mode', () => {
|
||||
@ -121,7 +121,7 @@ describe('MeetingLayoutComponent', () => {
|
||||
describe('Last Speakers Layout Mode', () => {
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
layoutModeSubject.next(MeetLayoutMode.LAST_SPEAKERS);
|
||||
layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@ -238,7 +238,7 @@ describe('MeetingLayoutComponent', () => {
|
||||
describe('Participant Cleanup', () => {
|
||||
it('should remove disconnected participants from active speakers', () => {
|
||||
fixture.detectChanges();
|
||||
layoutModeSubject.next(MeetLayoutMode.LAST_SPEAKERS);
|
||||
layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC);
|
||||
fixture.detectChanges();
|
||||
|
||||
const mockParticipants = createMockParticipants(5);
|
||||
@ -274,7 +274,7 @@ describe('MeetingLayoutComponent', () => {
|
||||
describe('Performance Optimizations', () => {
|
||||
it('should not process events in DEFAULT mode', () => {
|
||||
fixture.detectChanges();
|
||||
layoutModeSubject.next(MeetLayoutMode.DEFAULT);
|
||||
layoutModeSubject.next(MeetLayoutMode.MOSAIC);
|
||||
fixture.detectChanges();
|
||||
|
||||
const mockParticipants = createMockParticipants(5);
|
||||
@ -294,7 +294,7 @@ describe('MeetingLayoutComponent', () => {
|
||||
|
||||
it('should not process empty speaker arrays', () => {
|
||||
fixture.detectChanges();
|
||||
layoutModeSubject.next(MeetLayoutMode.LAST_SPEAKERS);
|
||||
layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC);
|
||||
fixture.detectChanges();
|
||||
|
||||
const mockParticipants = createMockParticipants(5);
|
||||
|
||||
@ -52,7 +52,7 @@ export class MeetingLayoutComponent {
|
||||
private readonly remoteParticipants = computed(() => this.meetingContextService.remoteParticipants());
|
||||
|
||||
private readonly layoutMode = toSignal(this.layoutService.layoutMode$, {
|
||||
initialValue: MeetLayoutMode.LAST_SPEAKERS
|
||||
initialValue: MeetLayoutMode.SMART_MOSAIC
|
||||
});
|
||||
|
||||
/**
|
||||
@ -64,7 +64,7 @@ export class MeetingLayoutComponent {
|
||||
/**
|
||||
* Computed signal that determines if last speakers layout is enabled
|
||||
*/
|
||||
private readonly isLastSpeakersLayoutEnabled = computed(() => this.layoutMode() === MeetLayoutMode.LAST_SPEAKERS);
|
||||
private readonly isLastSpeakersLayoutEnabled = computed(() => this.layoutMode() === MeetLayoutMode.SMART_MOSAIC);
|
||||
|
||||
/**
|
||||
* Computed signal that provides the filtered list of participants to display.
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
<!-- Grid Layout Configuration Section -->
|
||||
<div class="layout-section">
|
||||
<div class="section-header">
|
||||
<mat-icon class="section-icon material-symbols-outlined">browse</mat-icon>
|
||||
<h4 class="section-title">Layout settings</h4>
|
||||
</div>
|
||||
|
||||
<!-- Layout Mode Selection -->
|
||||
<div class="layout-mode-container">
|
||||
<mat-radio-group
|
||||
class="layout-radio-group"
|
||||
[(ngModel)]="layoutMode"
|
||||
(ngModelChange)="onLayoutModeChange($event)"
|
||||
aria-label="Select layout mode"
|
||||
>
|
||||
<mat-radio-button [value]="LayoutMode.MOSAIC" class="layout-radio-option">
|
||||
<div class="radio-content">
|
||||
<span class="radio-label">Mosaic</span>
|
||||
<span class="radio-description">Shows all participants in a unified grid</span>
|
||||
</div>
|
||||
</mat-radio-button>
|
||||
|
||||
<mat-radio-button [value]="LayoutMode.SMART_MOSAIC" class="layout-radio-option">
|
||||
<div class="radio-content">
|
||||
<span class="radio-label">Smart Mosaic</span>
|
||||
<span class="radio-description">Shows a limited number of active participants</span>
|
||||
</div>
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
|
||||
<!-- Participant Count Selection (only visible in Smart mode) -->
|
||||
@if (isSmartMode()) {
|
||||
<div class="participant-count-container">
|
||||
<mat-label class="input-label">Number of visible participants</mat-label>
|
||||
<p class="helper-text">Choose how many remote participants are shown in the grid</p>
|
||||
<div class="slider-container">
|
||||
<mat-slider
|
||||
class="participant-slider"
|
||||
[min]="1"
|
||||
[max]="6"
|
||||
[step]="1"
|
||||
[displayWith]="formatLabel"
|
||||
discrete
|
||||
>
|
||||
<input
|
||||
matSliderThumb
|
||||
[(ngModel)]="participantCount"
|
||||
(ngModelChange)="onParticipantCountChange($event)"
|
||||
aria-label="Number of participants to display"
|
||||
/>
|
||||
</mat-slider>
|
||||
<span class="participant-count-value">{{ participantCount() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@ -0,0 +1,154 @@
|
||||
.layout-section {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0 4px;
|
||||
|
||||
.section-icon {
|
||||
color: var(--ov-text-surface-color);
|
||||
font-size: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--ov-text-surface-color);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-mode-container {
|
||||
.input-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--ov-text-surface-color);
|
||||
margin-bottom: 12px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.layout-radio-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.layout-radio-option {
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
margin: 0;
|
||||
|
||||
.radio-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
margin-left: 8px;
|
||||
|
||||
.radio-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--ov-text-surface-color);
|
||||
}
|
||||
|
||||
.radio-description {
|
||||
font-size: 12px;
|
||||
color: var(--ov-text-secondary-color);
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.participant-count-container {
|
||||
padding: 16px;
|
||||
border-radius: var(--ov-surface-radius);
|
||||
border: 1px solid var(--ov-border-color);
|
||||
|
||||
.input-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--ov-text-surface-color);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.participant-slider {
|
||||
flex: 1;
|
||||
--mdc-slider-active-track-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-active-track-shape: 9999px;
|
||||
--mdc-slider-disabled-active-track-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-disabled-handle-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-disabled-inactive-track-color: rgba(var(--ov-accent-action-color), 0.2);
|
||||
--mdc-slider-focus-handle-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-handle-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-hover-handle-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-inactive-track-color: rgba(var(--ov-accent-action-color), 0.2);
|
||||
--mdc-slider-inactive-track-shape: 9999px;
|
||||
--mdc-slider-label-container-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-with-overlap-handle-outline-color: var(--ov-accent-action-color);
|
||||
--mdc-slider-with-tick-marks-active-container-color: white;
|
||||
--mdc-slider-with-tick-marks-disabled-container-color: white;
|
||||
--mdc-slider-with-tick-marks-inactive-container-color: rgba(var(--ov-accent-action-color), 0.5);
|
||||
}
|
||||
|
||||
.participant-count-value {
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--ov-text-surface-color);
|
||||
padding: 6px 10px;
|
||||
background-color: var(--ov-accent-action-color);
|
||||
border-radius: var(--ov-surface-radius);
|
||||
}
|
||||
}
|
||||
|
||||
.helper-text {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--ov-text-secondary-color);
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive adjustments
|
||||
@media (max-width: 768px) {
|
||||
.layout-section {
|
||||
.participant-count-container {
|
||||
padding: 12px;
|
||||
|
||||
.slider-container {
|
||||
.participant-count-value {
|
||||
min-width: 28px;
|
||||
font-size: 14px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Custom radio button styles for this component
|
||||
.layout-radio-option {
|
||||
::ng-deep .mdc-radio {
|
||||
&:hover {
|
||||
.mdc-radio__outer-circle {
|
||||
border-color: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MeetingSettingsPanelComponent } from './meeting-settings-panel.component';
|
||||
|
||||
describe('MeetingSettingsPanelComponent', () => {
|
||||
let component: MeetingSettingsPanelComponent;
|
||||
let fixture: ComponentFixture<MeetingSettingsPanelComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MeetingSettingsPanelComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MeetingSettingsPanelComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,79 @@
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MeetLayoutMode } from '../../../models/layout.model';
|
||||
|
||||
/**
|
||||
* Component for additional settings in the Settings Panel.
|
||||
* This component allows users to configure grid layout preferences including:
|
||||
* - Layout mode (Mosaic or Mosaic Smart)
|
||||
* - Number of participants to display in Smart mode
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-meeting-settings-panel',
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatIconModule,
|
||||
MatListModule,
|
||||
MatRadioModule,
|
||||
MatSliderModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
FormsModule
|
||||
],
|
||||
templateUrl: './meeting-settings-panel.component.html',
|
||||
styleUrl: './meeting-settings-panel.component.scss'
|
||||
})
|
||||
export class MeetingSettingsPanelComponent {
|
||||
/**
|
||||
* Expose LayoutMode enum to template
|
||||
*/
|
||||
readonly LayoutMode = MeetLayoutMode;
|
||||
|
||||
/**
|
||||
* Current selected layout mode
|
||||
*/
|
||||
layoutMode = signal<MeetLayoutMode>(MeetLayoutMode.MOSAIC);
|
||||
|
||||
/**
|
||||
* Number of participants to display in Smart mode
|
||||
* Range: 1-20
|
||||
*/
|
||||
participantCount = signal<number>(6);
|
||||
|
||||
/**
|
||||
* Computed property to check if Smart mode is active
|
||||
*/
|
||||
isSmartMode = computed(() => this.layoutMode() === MeetLayoutMode.SMART_MOSAIC);
|
||||
|
||||
/**
|
||||
* Handler for layout mode change
|
||||
*/
|
||||
onLayoutModeChange(mode: MeetLayoutMode): void {
|
||||
this.layoutMode.set(mode);
|
||||
console.log('Layout mode changed to:', mode);
|
||||
// TODO: Integrate with layout service when available
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for participant count change
|
||||
*/
|
||||
onParticipantCountChange(count: number): void {
|
||||
this.participantCount.set(count);
|
||||
console.log('Participant count changed to:', count);
|
||||
// TODO: Integrate with layout service when available
|
||||
}
|
||||
|
||||
/**
|
||||
* Format label for the participant count slider
|
||||
*/
|
||||
formatLabel(value: number): string {
|
||||
return `${value}`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
<!-- Grid Layout Settings Button -->
|
||||
<button
|
||||
mat-menu-item
|
||||
id="grid-layout-settings-btn"
|
||||
(click)="onOpenSettings()"
|
||||
[matTooltip]="isMobileView() ? '' : 'Configure grid layout'"
|
||||
>
|
||||
<mat-icon class="material-symbols-outlined">browser</mat-icon>
|
||||
<span>Adjust Layout</span>
|
||||
</button>
|
||||
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MeetingToolbarMoreOptionsButtonsComponent } from './meeting-toolbar-more-options-buttons.component';
|
||||
|
||||
describe('MeetingToolbarMoreOptionsButtonsComponent', () => {
|
||||
let component: MeetingToolbarMoreOptionsButtonsComponent;
|
||||
let fixture: ComponentFixture<MeetingToolbarMoreOptionsButtonsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MeetingToolbarMoreOptionsButtonsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MeetingToolbarMoreOptionsButtonsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,53 @@
|
||||
import { Component, computed, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { PanelService, ViewportService, PanelType } from 'openvidu-components-angular';
|
||||
|
||||
/**
|
||||
* Component for additional menu items in the toolbar's "More Options" menu.
|
||||
* This component handles custom actions like opening the settings panel for grid layout changes.
|
||||
* It follows the responsive pattern from openvidu-components-angular, adapting to mobile/tablet/desktop views.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-meeting-toolbar-more-options-buttons',
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule,
|
||||
MatTooltipModule
|
||||
],
|
||||
templateUrl: './meeting-toolbar-more-options-buttons.component.html',
|
||||
styleUrl: './meeting-toolbar-more-options-buttons.component.scss'
|
||||
})
|
||||
export class MeetingToolbarMoreOptionsButtonsComponent {
|
||||
/**
|
||||
* Viewport service for responsive behavior detection
|
||||
* Injected from openvidu-components-angular
|
||||
*/
|
||||
private viewportService = inject(ViewportService);
|
||||
|
||||
/**
|
||||
* Panel service for opening/closing panels
|
||||
* Injected from openvidu-components-angular
|
||||
*/
|
||||
private panelService = inject(PanelService);
|
||||
|
||||
/**
|
||||
* Computed properties for responsive button behavior
|
||||
* These follow the same pattern as toolbar-media-buttons component
|
||||
*/
|
||||
readonly isMobileView = computed(() => this.viewportService.isMobile());
|
||||
readonly isTabletView = computed(() => this.viewportService.isTablet());
|
||||
readonly isDesktopView = computed(() => this.viewportService.isDesktop());
|
||||
|
||||
/**
|
||||
* Opens the settings panel to allow users to change grid layout
|
||||
*/
|
||||
onOpenSettings(): void {
|
||||
this.panelService.togglePanel(PanelType.SETTINGS);
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,11 @@ export enum MeetLayoutMode {
|
||||
/**
|
||||
* Default layout mode shows all participants in a grid
|
||||
*/
|
||||
DEFAULT = 'DEFAULT',
|
||||
MOSAIC = 'MOSAIC',
|
||||
|
||||
/**
|
||||
* The layout mode that shows the last (x) speakers in a grid.
|
||||
* The layout mode that shows the last (N) speakers in a grid.
|
||||
* Optimized for large meetings.
|
||||
*/
|
||||
LAST_SPEAKERS = 'LAST_SPEAKERS'
|
||||
SMART_MOSAIC = 'SMART_MOSAIC'
|
||||
}
|
||||
|
||||
@ -60,6 +60,11 @@
|
||||
<ng-content select="ov-meeting-toolbar-buttons[slot='additional-buttons']"></ng-content>
|
||||
</div>
|
||||
|
||||
<!-- Toolbar More Options Additional Items -->
|
||||
<ng-container *ovToolbarMoreOptionsAdditionalMenuItems>
|
||||
<ng-content select="ov-meeting-toolbar-more-options-buttons[slot='additional-buttons']"></ng-content>
|
||||
</ng-container>
|
||||
|
||||
<!-- Share Link Panel After Local Participant -->
|
||||
<div *ovParticipantPanelAfterLocalParticipant>
|
||||
<ng-content select="ov-meeting-share-link-panel[slot='after-local-participant']"></ng-content>
|
||||
@ -74,6 +79,10 @@
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-container *ovSettingsPanelGeneralAdditionalElements>
|
||||
<ng-content select="ov-meeting-settings-panel[slot='additional-general-elements']"></ng-content>
|
||||
</ng-container>
|
||||
|
||||
<!-- Custom layout component -->
|
||||
<ng-container *ovLayout>
|
||||
<ng-content select="ov-meeting-layout[slot='layout']"></ng-content>
|
||||
|
||||
@ -8,7 +8,7 @@ import { MeetStorageService } from './storage.service';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MeetLayoutService extends LayoutService {
|
||||
private layoutMode: MeetLayoutMode = MeetLayoutMode.DEFAULT;
|
||||
private layoutMode: MeetLayoutMode = MeetLayoutMode.MOSAIC;
|
||||
layoutModeSubject: Subject<MeetLayoutMode> = new Subject<MeetLayoutMode>();
|
||||
layoutMode$: Observable<MeetLayoutMode> = this.layoutModeSubject.asObservable();
|
||||
|
||||
@ -35,7 +35,7 @@ export class MeetLayoutService extends LayoutService {
|
||||
if (layoutMode && Object.values(MeetLayoutMode).includes(layoutMode)) {
|
||||
this.layoutMode = layoutMode;
|
||||
} else {
|
||||
this.layoutMode = MeetLayoutMode.DEFAULT;
|
||||
this.layoutMode = MeetLayoutMode.MOSAIC;
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ export class MeetLayoutService extends LayoutService {
|
||||
* @returns {boolean} `true` if the layout mode is set to `LAST_SPEAKERS`, otherwise `false`.
|
||||
*/
|
||||
isLastSpeakersLayoutEnabled(): boolean {
|
||||
return this.layoutMode === MeetLayoutMode.LAST_SPEAKERS;
|
||||
return this.layoutMode === MeetLayoutMode.SMART_MOSAIC;
|
||||
}
|
||||
|
||||
setLayoutMode(layoutMode: MeetLayoutMode) {
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
<ov-meeting>
|
||||
<ov-meeting-toolbar-buttons slot="additional-buttons"></ov-meeting-toolbar-buttons>
|
||||
<ov-meeting-toolbar-more-options-buttons slot="additional-buttons"></ov-meeting-toolbar-more-options-buttons>
|
||||
<ov-meeting-share-link-panel slot="after-local-participant"></ov-meeting-share-link-panel>
|
||||
|
||||
<ov-meeting-participant-panel-item slot="participant-panel-item"></ov-meeting-participant-panel-item>
|
||||
<ov-meeting-settings-panel slot="additional-general-elements"></ov-meeting-settings-panel>
|
||||
<ov-meeting-layout slot="layout"></ov-meeting-layout>
|
||||
</ov-meeting>
|
||||
|
||||
@ -4,7 +4,9 @@ import {
|
||||
MeetingLayoutComponent,
|
||||
MeetingParticipantPanelItemComponent,
|
||||
MeetingShareLinkPanelComponent,
|
||||
MeetingToolbarButtonsComponent
|
||||
MeetingToolbarButtonsComponent,
|
||||
MeetingSettingsPanelComponent,
|
||||
MeetingToolbarMoreOptionsButtonsComponent
|
||||
} from '@openvidu-meet/shared-components';
|
||||
|
||||
@Component({
|
||||
@ -14,7 +16,9 @@ import {
|
||||
MeetingToolbarButtonsComponent,
|
||||
MeetingShareLinkPanelComponent,
|
||||
MeetingParticipantPanelItemComponent,
|
||||
MeetingLayoutComponent
|
||||
MeetingLayoutComponent,
|
||||
MeetingToolbarMoreOptionsButtonsComponent,
|
||||
MeetingSettingsPanelComponent
|
||||
],
|
||||
templateUrl: './app-ce-meeting.component.html',
|
||||
styleUrl: './app-ce-meeting.component.scss'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user