ov-components: add toolbar media buttons component

master
Carlos Santos 2025-09-16 19:42:37 +02:00
parent 0a49ca91d8
commit c65b5c8a18
9 changed files with 538 additions and 263 deletions

View File

@ -0,0 +1,188 @@
<!-- Camera button -->
@if (showCameraButton) {
<button
id="camera-btn"
mat-icon-button
(click)="onCameraToggle()"
[disabled]="isConnectionLost || !hasVideoDevices || cameraMuteChanging"
[class.disabled]="!isCameraEnabled"
[matTooltip]="isCameraEnabled ? ('TOOLBAR.STOP_VIDEO' | translate) : ('TOOLBAR.START_VIDEO' | translate)"
[matTooltipDisabled]="!hasVideoDevices"
>
<mat-icon [id]="isCameraEnabled ? 'videocam' : 'videocam_off'">
{{ isCameraEnabled ? 'videocam' : 'videocam_off' }}
</mat-icon>
</button>
}
<!-- Microphone button -->
@if (showMicrophoneButton) {
<button
id="mic-btn"
mat-icon-button
(click)="onMicrophoneToggle()"
[disabled]="isConnectionLost || !hasAudioDevices || microphoneMuteChanging"
[class.disabled]="!isMicrophoneEnabled"
[matTooltip]="isMicrophoneEnabled ? ('TOOLBAR.MUTE_AUDIO' | translate) : ('TOOLBAR.UNMUTE_AUDIO' | translate)"
[matTooltipDisabled]="!hasAudioDevices"
>
<mat-icon [id]="isMicrophoneEnabled ? 'mic' : 'mic_off'">
{{ isMicrophoneEnabled ? 'mic' : 'mic_off' }}
</mat-icon>
</button>
}
<!-- Enable Screenshare button -->
@if (!isMinimal && showScreenshareButton) {
<button
mat-icon-button
id="screenshare-btn"
[matMenuTriggerFor]="isScreenShareEnabled ? screenshareMenu : null"
[disabled]="isConnectionLost"
[class.active-btn]="isScreenShareEnabled"
matTooltip="{{ isScreenShareEnabled ? ('TOOLBAR.DISABLE_SCREEN' | translate) : ('TOOLBAR.ENABLE_SCREEN' | translate) }}"
(click)="!isScreenShareEnabled && onScreenShareToggle()"
>
<mat-icon>screen_share</mat-icon>
</button>
<!-- Screenshare button menu -->
<mat-menu #screenshareMenu="matMenu" id="screenshare-menu">
<button mat-menu-item (click)="onScreenTrackReplace()" id="replace-screen-button">
<mat-icon>picture_in_picture</mat-icon>
<span>{{ 'STREAM.REPLACE_SCREEN' | translate }}</span>
</button>
<mat-divider class="divider"></mat-divider>
<button mat-menu-item (click)="onScreenShareToggle()" id="disable-screen-button">
<mat-icon>stop_screen_share</mat-icon>
<span>{{ 'TOOLBAR.DISABLE_SCREEN' | translate }}</span>
</button>
</mat-menu>
}
<ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'beforeMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container>
<!-- More options button -->
@if (!isMinimal && showMoreOptionsButton) {
<button
mat-icon-button
id="more-options-btn"
[matMenuTriggerFor]="settingsMenu"
[disabled]="isConnectionLost"
matTooltip="{{ 'TOOLBAR.MORE_OPTIONS' | translate }}"
>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #settingsMenu="matMenu" id="more-options-menu">
<!-- Fullscreen button -->
@if (showFullscreenButton) {
<button mat-menu-item id="fullscreen-btn" (click)="onFullscreenToggle()">
<mat-icon>{{ isFullscreenActive ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
<span>{{ isFullscreenActive ? ('TOOLBAR.EXIT_FULLSCREEN' | translate) : ('TOOLBAR.FULLSCREEN' | translate) }}</span>
</button>
}
<!-- Recording button -->
@if (showRecordingButton) {
<button
mat-menu-item
id="recording-btn"
[disabled]="
recordingStatus === _recordingStatus.STARTING ||
recordingStatus === _recordingStatus.STOPPING ||
!hasRoomTracksPublished
"
[matTooltip]="!hasRoomTracksPublished ? ('TOOLBAR.NO_TRACKS_PUBLISHED' | translate) : ''"
(click)="onRecordingToggle()"
>
<mat-icon color="warn">radio_button_checked</mat-icon>
<span>
{{
recordingStatus === _recordingStatus.STOPPED ||
recordingStatus === _recordingStatus.STOPPING ||
recordingStatus === _recordingStatus.FAILED
? ('TOOLBAR.START_RECORDING' | translate)
: ('TOOLBAR.STOP_RECORDING' | translate)
}}
</span>
</button>
}
<!-- View recordings button -->
@if (showViewRecordingsButton) {
<button mat-menu-item id="view-recordings-btn" (click)="onViewRecordingsClick()">
<mat-icon>video_library</mat-icon>
<span>{{ 'TOOLBAR.VIEW_RECORDINGS' | translate }}</span>
</button>
}
<!-- Broadcasting button -->
@if (showBroadcastingButton) {
<button
mat-menu-item
id="toolbar-broadcasting-btn"
[disabled]="broadcastingStatus === _broadcastingStatus.STARTING || recordingStatus === _broadcastingStatus.STOPPING"
(click)="onBroadcastingToggle()"
>
<mat-icon>sensors</mat-icon>
<span>
{{
broadcastingStatus === _broadcastingStatus.STOPPED ||
broadcastingStatus === _broadcastingStatus.STOPPING ||
broadcastingStatus === _broadcastingStatus.FAILED
? ('PANEL.STREAMING.START' | translate)
: ('PANEL.STREAMING.STOP' | translate)
}}
</span>
</button>
}
<!-- Virtual background button -->
@if (showBackgroundEffectsButton) {
<button mat-menu-item id="virtual-bg-btn" [disabled]="!isCameraEnabled" (click)="onBackgroundEffectsToggle()">
<mat-icon><span class="material-symbols-outlined">background_replace</span></mat-icon>
<span>{{ 'TOOLBAR.BACKGROUND' | translate }}</span>
</button>
}
<!-- Captions button -->
<!-- <button
*ngIf="!isMinimal && showCaptionsButton"
[disabled]="isConnectionLost"
mat-menu-item
id="captions-btn"
(click)="onCaptionsToggle()"
>
<mat-icon>closed_caption</mat-icon>
<span *ngIf="captionsEnabled">{{ 'TOOLBAR.DISABLE_CAPTIONS' | translate }}</span>
<span *ngIf="!captionsEnabled">{{ 'TOOLBAR.ENABLE_CAPTIONS' | translate }}</span>
</button> -->
<!-- Divider before settings -->
@if (showSettingsButton) {
<mat-divider class="divider"></mat-divider>
}
<!-- Settings button -->
@if (showSettingsButton) {
<button mat-menu-item id="toolbar-settings-btn" (click)="onSettingsToggle()">
<mat-icon>settings</mat-icon>
<span>{{ 'TOOLBAR.SETTINGS' | translate }}</span>
</button>
}
</mat-menu>
}
<!-- External additional buttons -->
<ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'afterMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container>
<!-- Leave session button -->
@if (showLeaveButton) {
<button mat-icon-button (click)="onLeaveClick()" id="leave-btn" matTooltip="{{ 'TOOLBAR.LEAVE' | translate }}">
<mat-icon>call_end</mat-icon>
</button>
}

View File

@ -0,0 +1,123 @@
:host {
display: flex;
justify-content: center;
align-items: center;
.mat-mdc-icon-button {
--mat-mdc-button-persistent-ripple-color: transparent !important;
--mat-mdc-button-ripple-color: transparent !important;
}
mat-icon {
font-size: 24px;
}
button {
border-radius: var(--ov-toolbar-buttons-radius);
color: var(--ov-secondary-action-color);
&.disabled {
background-color: var(--ov-error-color) !important;
color: #fff !important;
}
}
button:not(mat-menu-item),
button:not(.mat-mdc-menu-item) ::ng-deep button:not(mat-menu-item),
::ng-deep button:not(#screenshare-menu) {
background-color: var(--ov-primary-action-color);
color: var(--ov-secondary-action-color);
margin: 6px;
}
#screenshare-menu {
}
#disable-screen-button > mat-icon {
color: var(--ov-error-color) !important;
}
.active-btn,
::ng-deep .active-btn {
background-color: var(--ov-accent-action-color) !important;
}
#leave-btn {
background-color: var(--ov-error-color) !important;
border-radius: var(--ov-leave-button-radius) !important;
width: 65px !important;
color: #ffffff !important;
}
.mat-mdc-icon-button[disabled] {
color: #fff;
}
.divider {
margin: 8px 0px;
}
.blink {
animation: blinker 1.5s linear infinite;
}
/* Animation for general blinking */
@keyframes blinker {
50% {
opacity: 0.3;
}
}
::ng-deep .mat-badge-content {
background-color: var(--ov-warn-color);
}
::ng-deep .mat-mdc-menu-item {
height: 40px;
line-height: 40px;
color: var(--ov-text-surface-color) !important;
}
::ng-deep .mat-mdc-menu-item mat-icon {
color: var(--ov-text-surface-color) !important;
}
::ng-deep #toolbar-broadcasting-btn > .mat-icon {
color: var(--ov-broadcasting-color) !important;
}
::ng-deep #recording-btn > .mat-icon {
color: var(--ov-recording-color) !important;
}
::ng-deep .mat-mdc-menu-panel {
border-radius: var(--ov-surface-radius) !important;
background-color: var(--ov-surface-color) !important;
box-shadow: var(--ov-border-shadow) !important;
}
/* Styles for XS screens */
@media (max-width: 599px) {
/* Animation for recording blinking */
@keyframes blinker-recording {
50% {
background-color: var(--ov-recording-color);
}
}
/* Animation for broadcasting blinking */
@keyframes blinker-broadcasting {
50% {
background-color: var(--ov-broadcasting-color);
}
}
/* Apply blinking animations to buttons */
.blinking-broadcasting-button {
animation: blinker-broadcasting 1.5s linear infinite;
}
.blinking-recording-button {
animation: blinker-recording 1.5s linear infinite;
}
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ToolbarMediaButtonsComponent } from './toolbar-media-buttons.component';
describe('ToolbarMediaButtonsComponent', () => {
let component: ToolbarMediaButtonsComponent;
let fixture: ComponentFixture<ToolbarMediaButtonsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ToolbarMediaButtonsComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ToolbarMediaButtonsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,140 @@
import { Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core';
import { RecordingStatus } from '../../../models/recording.model';
import { BroadcastingStatus } from '../../../models/broadcasting.model';
import { ToolbarAdditionalButtonsPosition } from '../../../models/toolbar.model';
@Component({
selector: 'ov-toolbar-media-buttons',
templateUrl: './toolbar-media-buttons.component.html',
styleUrl: './toolbar-media-buttons.component.scss',
standalone: false
})
export class ToolbarMediaButtonsComponent {
// Camera related inputs
@Input() showCameraButton: boolean = true;
@Input() isCameraEnabled: boolean = true;
@Input() cameraMuteChanging: boolean = false;
// Microphone related inputs
@Input() showMicrophoneButton: boolean = true;
@Input() isMicrophoneEnabled: boolean = true;
@Input() microphoneMuteChanging: boolean = false;
// Screenshare related inputs
@Input() showScreenshareButton: boolean = true;
@Input() isScreenShareEnabled: boolean = false;
// Device availability inputs
@Input() hasVideoDevices: boolean = true;
@Input() hasAudioDevices: boolean = true;
// Connection state inputs
@Input() isConnectionLost: boolean = false;
// UI state inputs
@Input() isMinimal: boolean = false;
// More options menu inputs
@Input() showMoreOptionsButton: boolean = true;
@Input() showFullscreenButton: boolean = true;
@Input() showRecordingButton: boolean = true;
@Input() showViewRecordingsButton: boolean = false;
@Input() showBroadcastingButton: boolean = true;
@Input() showBackgroundEffectsButton: boolean = true;
@Input() showCaptionsButton: boolean = true;
@Input() showSettingsButton: boolean = true;
// Fullscreen state
@Input() isFullscreenActive: boolean = false;
// Recording related inputs
@Input() recordingStatus: RecordingStatus = RecordingStatus.STOPPED;
@Input() hasRoomTracksPublished: boolean = false;
// Broadcasting related inputs
@Input() broadcastingStatus: BroadcastingStatus = BroadcastingStatus.STOPPED;
// Captions
@Input() captionsEnabled: boolean = false;
// Leave button
@Input() showLeaveButton: boolean = true;
// Additional buttons template
@Input() toolbarAdditionalButtonsTemplate: TemplateRef<any> | null = null;
@Input() additionalButtonsPosition: ToolbarAdditionalButtonsPosition | undefined;
// Status enums for template usage
_recordingStatus = RecordingStatus;
_broadcastingStatus = BroadcastingStatus;
// Media button outputs
@Output() cameraToggled = new EventEmitter<void>();
@Output() microphoneToggled = new EventEmitter<void>();
@Output() screenShareToggled = new EventEmitter<void>();
@Output() screenTrackReplaced = new EventEmitter<void>();
// More options menu outputs
@Output() fullscreenToggled = new EventEmitter<void>();
@Output() recordingToggled = new EventEmitter<void>();
@Output() viewRecordingsClicked = new EventEmitter<void>();
@Output() broadcastingToggled = new EventEmitter<void>();
@Output() backgroundEffectsToggled = new EventEmitter<void>();
@Output() captionsToggled = new EventEmitter<void>();
@Output() settingsToggled = new EventEmitter<void>();
// Leave button output
@Output() leaveClicked = new EventEmitter<void>();
// Event handler methods
onCameraToggle(): void {
this.cameraToggled.emit();
}
onMicrophoneToggle(): void {
this.microphoneToggled.emit();
}
onScreenShareToggle(): void {
this.screenShareToggled.emit();
}
onScreenTrackReplace(): void {
this.screenTrackReplaced.emit();
}
onFullscreenToggle(): void {
this.fullscreenToggled.emit();
}
onRecordingToggle(): void {
this.recordingToggled.emit();
}
onViewRecordingsClick(): void {
this.viewRecordingsClicked.emit();
}
onBroadcastingToggle(): void {
this.broadcastingToggled.emit();
}
onBackgroundEffectsToggle(): void {
this.backgroundEffectsToggled.emit();
}
onCaptionsToggle(): void {
this.captionsToggled.emit();
}
onSettingsToggle(): void {
this.settingsToggled.emit();
}
onLeaveClick(): void {
this.leaveClicked.emit();
}
}

View File

@ -40,203 +40,48 @@
<!-- Media and menu buttons container --> <!-- Media and menu buttons container -->
<div class="media-buttons-container" id="media-buttons-container"> <div class="media-buttons-container" id="media-buttons-container">
<!-- Camera button --> <ov-toolbar-media-buttons
<button [showCameraButton]="showCameraButton"
id="camera-btn" [isCameraEnabled]="isCameraEnabled"
mat-icon-button [cameraMuteChanging]="cameraMuteChanging"
*ngIf="showCameraButton" [showMicrophoneButton]="showMicrophoneButton"
(click)="toggleCamera()" [isMicrophoneEnabled]="isMicrophoneEnabled"
[disabled]="isConnectionLost || !hasVideoDevices || cameraMuteChanging" [microphoneMuteChanging]="microphoneMuteChanging"
[class.disabled]="!isCameraEnabled" [showScreenshareButton]="showScreenshareButton"
[matTooltip]="isCameraEnabled ? ('TOOLBAR.STOP_VIDEO' | translate) : ('TOOLBAR.START_VIDEO' | translate)" [isScreenShareEnabled]="isScreenShareEnabled"
[matTooltipDisabled]="!hasVideoDevices" [hasVideoDevices]="hasVideoDevices"
> [hasAudioDevices]="hasAudioDevices"
<mat-icon *ngIf="isCameraEnabled" id="videocam"> videocam </mat-icon> [isConnectionLost]="isConnectionLost"
<mat-icon *ngIf="!isCameraEnabled" id="videocam_off"> videocam_off </mat-icon> [isMinimal]="isMinimal"
</button> [showMoreOptionsButton]="showMoreOptionsButton"
[showFullscreenButton]="showFullscreenButton"
<!-- Microphone button --> [showRecordingButton]="showRecordingButton"
<button [showViewRecordingsButton]="showViewRecordingsButton"
id="mic-btn" [showBroadcastingButton]="showBroadcastingButton"
mat-icon-button [showBackgroundEffectsButton]="showBackgroundEffectsButton"
*ngIf="showMicrophoneButton" [showCaptionsButton]="showCaptionsButton"
(click)="toggleMicrophone()" [showSettingsButton]="showSettingsButton"
[disabled]="isConnectionLost || !hasAudioDevices || microphoneMuteChanging" [isFullscreenActive]="isFullscreenActive"
[class.disabled]="!isMicrophoneEnabled" [recordingStatus]="recordingStatus"
[matTooltip]="isMicrophoneEnabled ? ('TOOLBAR.MUTE_AUDIO' | translate) : ('TOOLBAR.UNMUTE_AUDIO' | translate)" [hasRoomTracksPublished]="hasRoomTracksPublished"
[matTooltipDisabled]="!hasAudioDevices" [broadcastingStatus]="broadcastingStatus"
> [captionsEnabled]="captionsEnabled"
<mat-icon *ngIf="isMicrophoneEnabled" id="mic"> mic </mat-icon> [showLeaveButton]="showLeaveButton"
<mat-icon *ngIf="!isMicrophoneEnabled" id="mic_off"> mic_off </mat-icon> [toolbarAdditionalButtonsTemplate]="toolbarAdditionalButtonsTemplate"
</button> [additionalButtonsPosition]="additionalButtonsPosition"
(cameraToggled)="toggleCamera()"
<!-- Enable Screenshare button --> (microphoneToggled)="toggleMicrophone()"
<button (screenShareToggled)="toggleScreenShare()"
mat-icon-button (screenTrackReplaced)="replaceScreenTrack()"
*ngIf="!isMinimal && showScreenshareButton && !isScreenShareEnabled" (fullscreenToggled)="toggleFullscreen()"
id="screenshare-btn" (recordingToggled)="toggleRecording()"
(click)="toggleScreenShare()" (viewRecordingsClicked)="onViewRecordingsClicked.emit()"
[disabled]="isConnectionLost" (broadcastingToggled)="toggleBroadcasting()"
matTooltip="{{ 'TOOLBAR.ENABLE_SCREEN' | translate }}" (backgroundEffectsToggled)="toggleBackgroundEffects()"
> (captionsToggled)="onCaptionsToggle()"
<mat-icon>screen_share</mat-icon> (settingsToggled)="toggleSettings()"
</button> (leaveClicked)="disconnect()"
<!-- Screenshare button menu --> ></ov-toolbar-media-buttons>
<button
mat-icon-button
*ngIf="!isMinimal && showScreenshareButton && isScreenShareEnabled"
id="screenshare-btn"
[matMenuTriggerFor]="screenshareMenu"
[disabled]="isConnectionLost"
class="active-btn"
matTooltip="{{ 'TOOLBAR.DISABLE_SCREEN' | translate }}"
>
<mat-icon>screen_share</mat-icon>
</button>
<mat-menu #screenshareMenu="matMenu" id="screenshare-menu">
<button mat-menu-item (click)="replaceScreenTrack()" id="replace-screen-button">
<mat-icon>picture_in_picture</mat-icon>
<span>{{ 'STREAM.REPLACE_SCREEN' | translate }}</span>
</button>
<mat-divider class="divider"></mat-divider>
<button mat-menu-item (click)="toggleScreenShare()" id="disable-screen-button">
<mat-icon>stop_screen_share</mat-icon>
<span>{{ 'TOOLBAR.DISABLE_SCREEN' | translate }}</span>
</button>
</mat-menu>
<ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'beforeMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container>
<!-- More options button -->
<button
mat-icon-button
id="more-options-btn"
*ngIf="!isMinimal && showMoreOptionsButton"
[matMenuTriggerFor]="settingsMenu"
[disabled]="isConnectionLost"
matTooltip="{{ 'TOOLBAR.MORE_OPTIONS' | translate }}"
>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #settingsMenu="matMenu" id="more-options-menu">
<!-- Fullscreen button -->
<button *ngIf="showFullscreenButton" mat-menu-item id="fullscreen-btn" (click)="toggleFullscreen()">
<mat-icon *ngIf="!isFullscreenActive">fullscreen</mat-icon>
<span *ngIf="!isFullscreenActive">{{ 'TOOLBAR.FULLSCREEN' | translate }}</span>
<mat-icon *ngIf="isFullscreenActive">fullscreen_exit</mat-icon>
<span *ngIf="isFullscreenActive">{{ 'TOOLBAR.EXIT_FULLSCREEN' | translate }}</span>
</button>
<!-- Recording button -->
<button
*ngIf="!isMinimal && showRecordingButton"
mat-menu-item
id="recording-btn"
[disabled]="
recordingStatus === _recordingStatus.STARTING ||
recordingStatus === _recordingStatus.STOPPING ||
!hasRoomTracksPublished
"
[matTooltip]="!hasRoomTracksPublished ? ('TOOLBAR.NO_TRACKS_PUBLISHED' | translate) : ''"
(click)="toggleRecording()"
>
<mat-icon color="warn">radio_button_checked</mat-icon>
@if (
recordingStatus === _recordingStatus.STOPPED ||
recordingStatus === _recordingStatus.STOPPING ||
recordingStatus === _recordingStatus.FAILED
) {
<span class="blink">
{{ 'TOOLBAR.START_RECORDING' | translate }}
</span>
} @else if (recordingStatus === _recordingStatus.STARTED || recordingStatus === _recordingStatus.STARTING) {
<span>{{ 'TOOLBAR.STOP_RECORDING' | translate }}</span>
}
</button>
<!-- View recordings button -->
@if (!isMinimal && showViewRecordingsButton) {
<button mat-menu-item id="view-recordings-btn" (click)="onViewRecordingsClicked.emit()">
<mat-icon>video_library</mat-icon>
<span>{{ 'TOOLBAR.VIEW_RECORDINGS' | translate }}</span>
</button>
}
<!-- Broadcasting button -->
<button
*ngIf="!isMinimal && showBroadcastingButton"
mat-menu-item
id="toolbar-broadcasting-btn"
[disabled]="broadcastingStatus === _broadcastingStatus.STARTING || recordingStatus === _broadcastingStatus.STOPPING"
(click)="toggleBroadcasting()"
>
<mat-icon>sensors</mat-icon>
<span
*ngIf="
broadcastingStatus === _broadcastingStatus.STOPPED ||
broadcastingStatus === _broadcastingStatus.STOPPING ||
broadcastingStatus === _broadcastingStatus.FAILED
"
>
{{ 'PANEL.STREAMING.START' | translate }}
</span>
<span *ngIf="broadcastingStatus === _broadcastingStatus.STARTED || broadcastingStatus === _broadcastingStatus.STARTING">
{{ 'PANEL.STREAMING.STOP' | translate }}
</span>
</button>
<!-- Virtual background button -->
<button
*ngIf="!isMinimal && showBackgroundEffectsButton"
[disabled]="!isCameraEnabled"
mat-menu-item
id="virtual-bg-btn"
(click)="toggleBackgroundEffects()"
>
<mat-icon><span class="material-symbols-outlined"> background_replace </span></mat-icon>
<span>{{ 'TOOLBAR.BACKGROUND' | translate }}</span>
</button>
<!-- Captions button -->
<!-- <button
*ngIf="!isMinimal && showCaptionsButton"
[disabled]="isConnectionLost"
mat-menu-item
id="captions-btn"
(click)="toggleCaptions()"
>
<mat-icon>closed_caption</mat-icon>
<span *ngIf="captionsEnabled">{{ 'TOOLBAR.DISABLE_CAPTIONS' | translate }}</span>
<span *ngIf="!captionsEnabled">{{ 'TOOLBAR.ENABLE_CAPTIONS' | translate }}</span>
</button> -->
<mat-divider class="divider" *ngIf="!isMinimal && showSettingsButton"></mat-divider>
<!-- Settings button -->
<button *ngIf="!isMinimal && showSettingsButton" mat-menu-item id="toolbar-settings-btn" (click)="toggleSettings()">
<mat-icon>settings</mat-icon>
<span>{{ 'TOOLBAR.SETTINGS' | translate }}</span>
</button>
</mat-menu>
<!-- External additional buttons -->
<ng-container *ngIf="toolbarAdditionalButtonsTemplate && additionalButtonsPosition && additionalButtonsPosition === 'afterMenu'">
<ng-container *ngTemplateOutlet="toolbarAdditionalButtonsTemplate"></ng-container>
</ng-container>
<!-- Leave session button -->
<button
mat-icon-button
*ngIf="showLeaveButton"
(click)="disconnect()"
id="leave-btn"
matTooltip="{{ 'TOOLBAR.LEAVE' | translate }}"
>
<mat-icon>call_end</mat-icon>
</button>
</div> </div>
<!-- Panel buttons (chat, participants, activities) --> <!-- Panel buttons (chat, participants, activities) -->

View File

@ -30,6 +30,13 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
// ov-toolbar-media-buttons {
// display: flex;
// justify-content: center;
// align-items: center;
// flex: 1;
// }
} }
.menu-buttons-container { .menu-buttons-container {
flex: 20%; flex: 20%;
@ -47,40 +54,9 @@
max-height: 100% !important; max-height: 100% !important;
} }
#media-buttons-container mat-icon {
font-size: 24px;
}
#media-buttons-container button,
#menu-buttons-container button { #menu-buttons-container button {
border-radius: var(--ov-toolbar-buttons-radius); border-radius: var(--ov-toolbar-buttons-radius);
color: var(--ov-secondary-action-color); color: var(--ov-secondary-action-color);
&.disabled {
background-color: var(--ov-error-color) !important;
color: #fff !important;
}
}
#media-buttons-container > button,
::ng-deep #media-buttons-container > button,
#media-buttons-container:not(#media-buttons-container > button) button,
/* Applying css for external additional buttons*/
::ng-deep #media-buttons-container:not(#media-buttons-container > button) button {
// width: 40px;
// height: 40px;
background-color: var(--ov-primary-action-color);
color: var(--ov-secondary-action-color);
margin: 6px;
}
#disable-screen-button > mat-icon {
color: var(--ov-error-color) !important;
}
.active-btn,
::ng-deep .active-btn {
background-color: var(--ov-accent-action-color) !important;
} }
#branding-logo { #branding-logo {
@ -146,34 +122,11 @@
animation: blinker 1.5s linear infinite; animation: blinker 1.5s linear infinite;
} }
#leave-btn {
background-color: var(--ov-error-color) !important;
border-radius: var(--ov-leave-button-radius) !important;
width: 65px !important;
color: #ffffff !important;
}
.mat-mdc-icon-button[disabled] {
color: #fff;
}
::ng-deep .mat-badge-content { ::ng-deep .mat-badge-content {
background-color: var(--ov-warn-color); background-color: var(--ov-warn-color);
} }
.divider {
margin: 8px 0px;
}
::ng-deep .mat-mdc-menu-item {
/* margin-bottom: 10px; */
height: 40px;
line-height: 40px;
}
/* Animation for general blinking */
@keyframes blinker {
50% {
opacity: 0.3;
}
}
/* Styles for XS screens */ /* Styles for XS screens */
@media (max-width: 599px) { @media (max-width: 599px) {

View File

@ -651,16 +651,16 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
/** /**
* @ignore * @ignore
*/ */
// toggleCaptions() { onCaptionsToggle() {
// if (this.openviduService.isOpenViduPro()) { // if (this.openviduService.isOpenViduPro()) {
// this.layoutService.toggleCaptions(); // this.layoutService.toggleCaptions();
// } else { // } else {
// this.actionService.openProFeatureDialog( // this.actionService.openProFeatureDialog(
// this.translateService.translate('PANEL.SETTINGS.CAPTIONS'), // this.translateService.translate('PANEL.SETTINGS.CAPTIONS'),
// this.translateService.translate('PANEL.PRO_FEATURE') // this.translateService.translate('PANEL.PRO_FEATURE')
// ); // );
// } // }
// } }
/** /**
* @ignore * @ignore

View File

@ -11,6 +11,7 @@ import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.com
import { SessionComponent } from './components/session/session.component'; import { SessionComponent } from './components/session/session.component';
import { StreamComponent } from './components/stream/stream.component'; import { StreamComponent } from './components/stream/stream.component';
import { ToolbarComponent } from './components/toolbar/toolbar.component'; import { ToolbarComponent } from './components/toolbar/toolbar.component';
import { ToolbarMediaButtonsComponent } from './components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component';
import { MediaElementComponent } from './components/media-element/media-element.component'; import { MediaElementComponent } from './components/media-element/media-element.component';
import { LinkifyPipe } from './pipes/linkify.pipe'; import { LinkifyPipe } from './pipes/linkify.pipe';
@ -76,7 +77,8 @@ const privateComponents = [
VideoDevicesComponent, VideoDevicesComponent,
AudioDevicesComponent, AudioDevicesComponent,
ParticipantNameInputComponent, ParticipantNameInputComponent,
LangSelectorComponent LangSelectorComponent,
ToolbarMediaButtonsComponent
]; ];
@NgModule({ @NgModule({

View File

@ -15,6 +15,7 @@ export * from './lib/components/panel/participants-panel/participant-panel-item/
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.component';
export * from './lib/components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component';
export * from './lib/components/videoconference/videoconference.component'; export * from './lib/components/videoconference/videoconference.component';
export * from './lib/config/openvidu-components-angular.config'; export * from './lib/config/openvidu-components-angular.config';
// Directives // Directives