mirror of https://github.com/OpenVidu/openvidu.git
openvidu-components: Added openvidu-angular documentation
parent
d81124150a
commit
ff2dc6d86b
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,8 @@
|
||||||
"lib:test": "ng test openvidu-angular --no-watch --code-coverage",
|
"lib:test": "ng test openvidu-angular --no-watch --code-coverage",
|
||||||
"lib:e2e": "tsc --project ./e2e && npx mocha --recursive --timeout 30000 ./e2e/dist/angular.test.js",
|
"lib:e2e": "tsc --project ./e2e && npx mocha --recursive --timeout 30000 ./e2e/dist/angular.test.js",
|
||||||
"lib:e2e-ci": "cross-env LAUNCH_MODE=CI npm run lib:e2e",
|
"lib:e2e-ci": "cross-env LAUNCH_MODE=CI npm run lib:e2e",
|
||||||
|
"lib:doc-build": "npx compodoc -p src/doc/tsconfig.doc.json -c src/doc/.compodocrc.json",
|
||||||
|
"lib:doc-serve": "npx compodoc -p src/doc/tsconfig.doc.json --watch --serve -c src/doc/.compodocrc.json",
|
||||||
"webcomponent:build": "./node_modules/@angular/cli/bin/ng.js build openvidu-webcomponent --configuration production && node ./openvidu-webcomponent-build.js",
|
"webcomponent:build": "./node_modules/@angular/cli/bin/ng.js build openvidu-webcomponent --configuration production && node ./openvidu-webcomponent-build.js",
|
||||||
"webcomponent:serve-testapp": "npx http-server ./e2e/webcomponent-app/",
|
"webcomponent:serve-testapp": "npx http-server ./e2e/webcomponent-app/",
|
||||||
"webcomponent:e2e": "tsc --project ./e2e && npx mocha --recursive --timeout 30000 ./e2e/dist/webcomponent.test.js",
|
"webcomponent:e2e": "tsc --project ./e2e && npx mocha --recursive --timeout 30000 ./e2e/dist/webcomponent.test.js",
|
||||||
|
@ -43,6 +45,7 @@
|
||||||
"@angular/compiler": "13.0.0",
|
"@angular/compiler": "13.0.0",
|
||||||
"@angular/compiler-cli": "13.0.0",
|
"@angular/compiler-cli": "13.0.0",
|
||||||
"@angular/elements": "13.0.0",
|
"@angular/elements": "13.0.0",
|
||||||
|
"@compodoc/compodoc": "^1.1.19",
|
||||||
"@types/chai": "4.3.0",
|
"@types/chai": "4.3.0",
|
||||||
"@types/mocha": "9.1.0",
|
"@types/mocha": "9.1.0",
|
||||||
"@types/node": "16.11.6",
|
"@types/node": "16.11.6",
|
||||||
|
|
|
@ -2,6 +2,10 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { PublisherSpeakingEvent, StreamManager } from 'openvidu-browser';
|
import { PublisherSpeakingEvent, StreamManager } from 'openvidu-browser';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-audio-wave',
|
selector: 'ov-audio-wave',
|
||||||
templateUrl: './audio-wave.component.html',
|
templateUrl: './audio-wave.component.html',
|
||||||
|
@ -9,7 +13,7 @@ import { PublisherSpeakingEvent, StreamManager } from 'openvidu-browser';
|
||||||
})
|
})
|
||||||
export class AudioWaveComponent implements OnInit, OnDestroy {
|
export class AudioWaveComponent implements OnInit, OnDestroy {
|
||||||
isSpeaking: boolean = false;
|
isSpeaking: boolean = false;
|
||||||
audioVolume: number = 0;
|
// audioVolume: number = 0;
|
||||||
|
|
||||||
private _streamManager: StreamManager;
|
private _streamManager: StreamManager;
|
||||||
|
|
||||||
|
@ -17,7 +21,7 @@ export class AudioWaveComponent implements OnInit, OnDestroy {
|
||||||
set streamManager(streamManager: StreamManager) {
|
set streamManager(streamManager: StreamManager) {
|
||||||
this._streamManager = streamManager;
|
this._streamManager = streamManager;
|
||||||
|
|
||||||
if(this._streamManager) {
|
if (this._streamManager) {
|
||||||
this._streamManager.on('publisherStartSpeaking', (event: PublisherSpeakingEvent) => {
|
this._streamManager.on('publisherStartSpeaking', (event: PublisherSpeakingEvent) => {
|
||||||
this.isSpeaking = true;
|
this.isSpeaking = true;
|
||||||
});
|
});
|
||||||
|
@ -34,12 +38,11 @@ export class AudioWaveComponent implements OnInit, OnDestroy {
|
||||||
// console.log('AUDIO VOLUME', this.audioVolume);
|
// console.log('AUDIO VOLUME', this.audioVolume);
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if(this._streamManager){
|
if (this._streamManager) {
|
||||||
this._streamManager.off('publisherStartSpeaking');
|
this._streamManager.off('publisherStartSpeaking');
|
||||||
this._streamManager.off('publisherStopSpeaking');
|
this._streamManager.off('publisherStopSpeaking');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-avatar-profile',
|
selector: 'ov-avatar-profile',
|
||||||
template: `
|
template: `
|
||||||
|
|
|
@ -13,8 +13,40 @@ import { ParticipantService } from '../../services/participant/participant.servi
|
||||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||||
import { LayoutService } from '../../services/layout/layout.service';
|
import { LayoutService } from '../../services/layout/layout.service';
|
||||||
import { StreamDirective } from '../../directives/template/openvidu-angular.directive';
|
import { StreamDirective } from '../../directives/template/openvidu-angular.directive';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **LayoutComponent** is hosted inside of the {@link VideoconferenceComponent}.
|
||||||
|
* It is in charge of displaying the participants streams layout.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
*
|
||||||
|
* <div>
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The LayoutComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovLayout** | {@link LayoutDirective} |
|
||||||
|
*
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* It is also providing us a way to **replace the {@link StreamComponent Stream Component}** (<span class="italic">which is hosted inside of it</span>) with a custom one.
|
||||||
|
* It will recognise the following directive in a child element.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovStream** | {@link StreamDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-layout',
|
selector: 'ov-layout',
|
||||||
templateUrl: './layout.component.html',
|
templateUrl: './layout.component.html',
|
||||||
|
@ -22,8 +54,14 @@ import { OpenViduAngularConfigService } from '../../services/config/openvidu-ang
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
|
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild(StreamDirective)
|
@ContentChild(StreamDirective)
|
||||||
set externalStream(externalStream: StreamDirective) {
|
set externalStream(externalStream: StreamDirective) {
|
||||||
// This directive will has value only when STREAM component tagget with '*ovStream' directive
|
// This directive will has value only when STREAM component tagget with '*ovStream' directive
|
||||||
|
@ -38,12 +76,10 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
protected localParticipantSubs: Subscription;
|
protected localParticipantSubs: Subscription;
|
||||||
protected remoteParticipantsSubs: Subscription;
|
protected remoteParticipantsSubs: Subscription;
|
||||||
|
|
||||||
constructor(
|
/**
|
||||||
protected layoutService: LayoutService,
|
* @ignore
|
||||||
protected participantService: ParticipantService,
|
*/
|
||||||
private libService: OpenViduAngularConfigService,
|
constructor(protected layoutService: LayoutService, protected participantService: ParticipantService, private cd: ChangeDetectorRef) {}
|
||||||
private cd: ChangeDetectorRef
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subscribeToParticipants();
|
this.subscribeToParticipants();
|
||||||
|
@ -51,10 +87,6 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
let timeout: number = 0;
|
let timeout: number = 0;
|
||||||
// if (this.libService.isWebcomponent()) {
|
|
||||||
// timeout = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.layoutService.initialize(timeout);
|
this.layoutService.initialize(timeout);
|
||||||
this.layoutService.update(timeout);
|
this.layoutService.update(timeout);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +99,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
this.layoutService.clear();
|
this.layoutService.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected subscribeToParticipants() {
|
private subscribeToParticipants() {
|
||||||
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
|
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
|
||||||
this.localParticipant = p;
|
this.localParticipant = p;
|
||||||
this.layoutService.update();
|
this.layoutService.update();
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface DialogData {
|
export interface DialogData {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
showActionButtons: boolean;
|
showActionButtons: boolean;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-dialog-template',
|
selector: 'ov-dialog-template',
|
||||||
|
|
|
@ -1,10 +1,43 @@
|
||||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
HostListener,
|
||||||
|
OnInit,
|
||||||
|
ViewChild
|
||||||
|
} from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { ChatMessage } from '../../../models/chat.model';
|
import { ChatMessage } from '../../../models/chat.model';
|
||||||
import { MenuType } from '../../../models/menu.model';
|
import { MenuType } from '../../../models/menu.model';
|
||||||
import { ChatService } from '../../../services/chat/chat.service';
|
import { ChatService } from '../../../services/chat/chat.service';
|
||||||
import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **ChatPanelComponent** is hosted inside of the {@link PanelComponent}.
|
||||||
|
* It is in charge of displaying the session chat.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The ChatPanelComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovChatPanel** | {@link ChatPanelDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-chat-panel',
|
selector: 'ov-chat-panel',
|
||||||
templateUrl: './chat-panel.component.html',
|
templateUrl: './chat-panel.component.html',
|
||||||
|
@ -12,16 +45,31 @@ import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class ChatPanelComponent implements OnInit, AfterViewInit {
|
export class ChatPanelComponent implements OnInit, AfterViewInit {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ViewChild('chatScroll') chatScroll: ElementRef;
|
@ViewChild('chatScroll') chatScroll: ElementRef;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ViewChild('chatInput') chatInput: ElementRef;
|
@ViewChild('chatInput') chatInput: ElementRef;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
messageList: ChatMessage[] = [];
|
messageList: ChatMessage[] = [];
|
||||||
isMenuOpened: boolean;
|
|
||||||
|
|
||||||
private chatMessageSubscription: Subscription;
|
private chatMessageSubscription: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(private chatService: ChatService, private menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
constructor(private chatService: ChatService, private menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@HostListener('document:keydown.escape', ['$event'])
|
@HostListener('document:keydown.escape', ['$event'])
|
||||||
onKeydownHandler(event: KeyboardEvent) {
|
onKeydownHandler(event: KeyboardEvent) {
|
||||||
if (this.menuService.isMenuOpened()) {
|
if (this.menuService.isMenuOpened()) {
|
||||||
|
@ -44,6 +92,9 @@ export class ChatPanelComponent implements OnInit, AfterViewInit {
|
||||||
if (this.chatMessageSubscription) this.chatMessageSubscription.unsubscribe();
|
if (this.chatMessageSubscription) this.chatMessageSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
eventKeyPress(event) {
|
eventKeyPress(event) {
|
||||||
// Pressed 'Enter' key
|
// Pressed 'Enter' key
|
||||||
if (event && event.keyCode === 13) {
|
if (event && event.keyCode === 13) {
|
||||||
|
@ -53,7 +104,7 @@ export class ChatPanelComponent implements OnInit, AfterViewInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(): void {
|
sendMessage(): void {
|
||||||
if(!!this.message) {
|
if (!!this.message) {
|
||||||
this.chatService.sendMessage(this.message);
|
this.chatService.sendMessage(this.message);
|
||||||
this.message = '';
|
this.message = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,42 @@ import { ChatPanelDirective, ParticipantsPanelDirective } from '../../directives
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../models/menu.model';
|
||||||
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **PanelComponent** is hosted inside of the {@link VideoconferenceComponent}.
|
||||||
|
* It is in charge of displaying the videoconference panels providing functionalities to the videoconference app
|
||||||
|
* such as the chat ({@link ChatPanelComponent}) and list of participants ({@link ParticipantsPanelComponent}) .
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The PanelComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovPanel** | {@link PanelDirective} |
|
||||||
|
*
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* It is also providing us a way to **replace the children panels** to the default panel.
|
||||||
|
* It will recognise the following directive in a child element.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovChatPanel** | {@link ChatPanelDirective} |
|
||||||
|
* | ***ovParticipantsPanel** | {@link ParticipantsPanelDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-panel',
|
selector: 'ov-panel',
|
||||||
templateUrl: './panel.component.html',
|
templateUrl: './panel.component.html',
|
||||||
|
@ -11,7 +47,14 @@ import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.ser
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class PanelComponent implements OnInit {
|
export class PanelComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('participantsPanel', { read: TemplateRef }) participantsPanelTemplate: TemplateRef<any>;
|
@ContentChild('participantsPanel', { read: TemplateRef }) participantsPanelTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('chatPanel', { read: TemplateRef }) chatPanelTemplate: TemplateRef<any>;
|
@ContentChild('chatPanel', { read: TemplateRef }) chatPanelTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
@ContentChild(ParticipantsPanelDirective)
|
@ContentChild(ParticipantsPanelDirective)
|
||||||
|
@ -34,23 +77,28 @@ export class PanelComponent implements OnInit {
|
||||||
|
|
||||||
isParticipantsPanelOpened: boolean;
|
isParticipantsPanelOpened: boolean;
|
||||||
isChatPanelOpened: boolean;
|
isChatPanelOpened: boolean;
|
||||||
menuSubscription: Subscription;
|
private menuSubscription: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(protected menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
constructor(protected menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subscribeToPanelToggling();
|
this.subscribeToPanelToggling();
|
||||||
}
|
}
|
||||||
subscribeToPanelToggling() {
|
|
||||||
this.menuSubscription = this.menuService.menuOpenedObs.pipe(skip(1)).subscribe((ev: { opened: boolean; type?: MenuType }) => {
|
|
||||||
this.isChatPanelOpened = ev.opened && ev.type === MenuType.CHAT;
|
|
||||||
this.isParticipantsPanelOpened = ev.opened && ev.type === MenuType.PARTICIPANTS;
|
|
||||||
this.cd.markForCheck();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.isChatPanelOpened = false;
|
this.isChatPanelOpened = false;
|
||||||
this.isParticipantsPanelOpened = false;
|
this.isParticipantsPanelOpened = false;
|
||||||
if (this.menuSubscription) this.menuSubscription.unsubscribe();
|
if (this.menuSubscription) this.menuSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private subscribeToPanelToggling() {
|
||||||
|
this.menuSubscription = this.menuService.menuOpenedObs.pipe(skip(1)).subscribe((ev: { opened: boolean; type?: MenuType }) => {
|
||||||
|
this.isChatPanelOpened = ev.opened && ev.type === MenuType.CHAT;
|
||||||
|
this.isParticipantsPanelOpened = ev.opened && ev.type === MenuType.PARTICIPANTS;
|
||||||
|
this.cd.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,54 @@ import { ParticipantPanelItemElementsDirective } from '../../../../directives/te
|
||||||
import { ParticipantAbstractModel } from '../../../../models/participant.model';
|
import { ParticipantAbstractModel } from '../../../../models/participant.model';
|
||||||
import { OpenViduAngularConfigService } from '../../../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **ParticipantPanelItemComponent** is hosted inside of the {@link ParticipantsPanelComponent}.
|
||||||
|
* It is in charge of displaying the participants information inside of the ParticipansPanelComponent.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
* <div>
|
||||||
|
* <h3>API Directives</h3>
|
||||||
|
*
|
||||||
|
* This component allows us to show or hide certain HTML elements with the following {@link https://angular.io/guide/attribute-directives Angular attribute directives}
|
||||||
|
* with the aim of fully customizing the ToolbarComponent.
|
||||||
|
*
|
||||||
|
* | **Name** | **Type** | **Reference** |
|
||||||
|
* | :----------------------------: | :-------: | :---------------------------------------------: |
|
||||||
|
* | **muteButton** | `boolean` | {@link ParticipantPanelItemMuteButtonDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link ApiDirectiveModule API Directives}</span>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* </div>
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The ParticipantPanelItemComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovParticipantPanelItem** | {@link ParticipantPanelItemDirective} |
|
||||||
|
*
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* It is also providing us a way to **add additional buttons** to the default participant panel item.
|
||||||
|
* It will recognise the following directive in a child element.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovParticipantPanelItemElements** | {@link ParticipantPanelItemElementsDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-participant-panel-item',
|
selector: 'ov-participant-panel-item',
|
||||||
templateUrl: './participant-panel-item.component.html',
|
templateUrl: './participant-panel-item.component.html',
|
||||||
|
@ -11,10 +59,20 @@ import { OpenViduAngularConfigService } from '../../../../services/config/openvi
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('participantPanelItemElements', { read: TemplateRef }) participantPanelItemElementsTemplate: TemplateRef<any>;
|
@ContentChild('participantPanelItemElements', { read: TemplateRef }) participantPanelItemElementsTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showMuteButton: boolean = true;
|
showMuteButton: boolean = true;
|
||||||
private muteButtonSub: Subscription;
|
private muteButtonSub: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild(ParticipantPanelItemElementsDirective)
|
@ContentChild(ParticipantPanelItemElementsDirective)
|
||||||
set externalItemElements(externalItemElements: ParticipantPanelItemElementsDirective) {
|
set externalItemElements(externalItemElements: ParticipantPanelItemElementsDirective) {
|
||||||
// This directive will has value only when ITEM ELEMENTS component tagget with '*ovParticipantPanelItemElements' directive
|
// This directive will has value only when ITEM ELEMENTS component tagget with '*ovParticipantPanelItemElements' directive
|
||||||
|
@ -25,11 +83,18 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set participant(p: ParticipantAbstractModel) {
|
set participant(participant: ParticipantAbstractModel) {
|
||||||
this._participant = p;
|
this._participant = participant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
_participant: ParticipantAbstractModel;
|
_participant: ParticipantAbstractModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(private libService: OpenViduAngularConfigService, private cd: ChangeDetectorRef) {}
|
constructor(private libService: OpenViduAngularConfigService, private cd: ChangeDetectorRef) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@ -39,6 +104,9 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
||||||
if (this.muteButtonSub) this.muteButtonSub.unsubscribe();
|
if (this.muteButtonSub) this.muteButtonSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleMuteForcibly() {
|
toggleMuteForcibly() {
|
||||||
this._participant.setMutedForcibly(!this._participant.isMutedForcibly);
|
this._participant.setMutedForcibly(!this._participant.isMutedForcibly);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,39 @@ import { SidenavMenuService } from '../../../..//services/sidenav-menu/sidenav-m
|
||||||
import { ParticipantPanelItemDirective } from '../../../../directives/template/openvidu-angular.directive';
|
import { ParticipantPanelItemDirective } from '../../../../directives/template/openvidu-angular.directive';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **ParticipantsPanelComponent** is hosted inside of the {@link PanelComponent}.
|
||||||
|
* It is in charge of displaying the participants connected to the session.
|
||||||
|
* This component is composed by the {@link ParticipantPanelItemComponent}.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The ParticipantsPanelComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovParticipantsPanel** | {@link ParticipantsPanelDirective} |
|
||||||
|
*
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* As the ParticipantsPanelComponent is composed by ParticipantPanelItemComponent, it is also providing us a way to **replace the participant item** with a custom one.
|
||||||
|
* It will recognise the following directive in a child element.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovParticipantPanelItem** | {@link ParticipantPanelItemDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-participants-panel',
|
selector: 'ov-participants-panel',
|
||||||
templateUrl: './participants-panel.component.html',
|
templateUrl: './participants-panel.component.html',
|
||||||
|
@ -15,8 +48,9 @@ export class ParticipantsPanelComponent implements OnInit, OnDestroy {
|
||||||
localParticipant: any;
|
localParticipant: any;
|
||||||
remoteParticipants: ParticipantAbstractModel[] = [];
|
remoteParticipants: ParticipantAbstractModel[] = [];
|
||||||
|
|
||||||
private localParticipantSubs: Subscription;
|
/**
|
||||||
private remoteParticipantsSubs: Subscription;
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('participantPanelItem', { read: TemplateRef }) participantPanelItemTemplate: TemplateRef<any>;
|
@ContentChild('participantPanelItem', { read: TemplateRef }) participantPanelItemTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
@ContentChild(ParticipantPanelItemDirective)
|
@ContentChild(ParticipantPanelItemDirective)
|
||||||
|
@ -28,16 +62,19 @@ export class ParticipantsPanelComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private localParticipantSubs: Subscription;
|
||||||
|
private remoteParticipantsSubs: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
protected participantService: ParticipantService,
|
protected participantService: ParticipantService,
|
||||||
protected menuService: SidenavMenuService,
|
protected menuService: SidenavMenuService,
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef
|
||||||
) {
|
) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p: ParticipantAbstractModel) => {
|
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p: ParticipantAbstractModel) => {
|
||||||
this.localParticipant = p;
|
this.localParticipant = p;
|
||||||
// Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
|
// Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
|
||||||
|
|
|
@ -13,6 +13,9 @@ import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
||||||
import { ParticipantService } from '../../services/participant/participant.service';
|
import { ParticipantService } from '../../services/participant/participant.service';
|
||||||
import { StorageService } from '../../services/storage/storage.service';
|
import { StorageService } from '../../services/storage/storage.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-pre-join',
|
selector: 'ov-pre-join',
|
||||||
templateUrl: './pre-join.component.html',
|
templateUrl: './pre-join.component.html',
|
||||||
|
|
|
@ -27,6 +27,11 @@ import { LayoutService } from '../../services/layout/layout.service';
|
||||||
import { Subscription, skip } from 'rxjs';
|
import { Subscription, skip } from 'rxjs';
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../models/menu.model';
|
||||||
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
import { PlatformService } from '../../services/platform/platform.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-session',
|
selector: 'ov-session',
|
||||||
|
@ -68,7 +73,8 @@ export class SessionComponent implements OnInit {
|
||||||
protected chatService: ChatService,
|
protected chatService: ChatService,
|
||||||
protected tokenService: TokenService,
|
protected tokenService: TokenService,
|
||||||
protected layoutService: LayoutService,
|
protected layoutService: LayoutService,
|
||||||
protected menuService: SidenavMenuService
|
protected menuService: SidenavMenuService,
|
||||||
|
private platformService: PlatformService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('SessionComponent');
|
this.log = this.loggerSrv.get('SessionComponent');
|
||||||
}
|
}
|
||||||
|
@ -107,9 +113,9 @@ export class SessionComponent implements OnInit {
|
||||||
|
|
||||||
await this.connectToSession();
|
await this.connectToSession();
|
||||||
// Workaround, firefox does not have audio when publisher join with muted camera
|
// Workaround, firefox does not have audio when publisher join with muted camera
|
||||||
// if (this.platformService.isFirefox() && !this.localUserService.hasCameraVideoActive()) {
|
// if (this.platformService.isFirefox() && !this.participantService.hasCameraVideoActive()) {
|
||||||
// this.openviduService.publishVideo(this.localUserService.getMyCameraPublisher(), true);
|
// this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);
|
||||||
// this.openviduService.publishVideo(this.localUserService.getMyCameraPublisher(), false);
|
// this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), false);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
<span *ngIf="videoSizeIcon === videoSizeIconEnum.NORMAL">Zoom out</span>
|
<span *ngIf="videoSizeIcon === videoSizeIconEnum.NORMAL">Zoom out</span>
|
||||||
<span *ngIf="videoSizeIcon === videoSizeIconEnum.BIG">Zoom in</span>
|
<span *ngIf="videoSizeIcon === videoSizeIconEnum.BIG">Zoom in</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item id="volumeButton" *ngIf="!this._stream.local" (click)="toggleSound()">
|
<button mat-menu-item id="volumeButton" *ngIf="!this._stream.local" (click)="toggleMuteForcibly()">
|
||||||
<mat-icon *ngIf="!_stream.participant.isMutedForcibly">volume_up</mat-icon>
|
<mat-icon *ngIf="!_stream.participant.isMutedForcibly">volume_up</mat-icon>
|
||||||
<span *ngIf="!_stream.participant.isMutedForcibly">Mute sound</span>
|
<span *ngIf="!_stream.participant.isMutedForcibly">Mute sound</span>
|
||||||
|
|
||||||
|
|
|
@ -14,44 +14,105 @@ import { StreamModel } from '../../models/participant.model';
|
||||||
import { ParticipantService } from '../../services/participant/participant.service';
|
import { ParticipantService } from '../../services/participant/participant.service';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **StreamComponent** is hosted inside of the {@link LayoutComponent}.
|
||||||
|
* It is in charge of displaying the participant video stream in the videoconference layout.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
* <div>
|
||||||
|
* <h3>API Directives</h3>
|
||||||
|
*
|
||||||
|
* This component allows us to show or hide certain HTML elements with the following {@link https://angular.io/guide/attribute-directives Angular attribute directives}
|
||||||
|
* with the aim of fully customizing the StreamComponent.
|
||||||
|
*
|
||||||
|
* | **Parameter** | **Type** | **Reference** |
|
||||||
|
* | :----------------------------: | :-------: | :---------------------------------------------: |
|
||||||
|
* | **displayParticipantName** | `boolean` | {@link StreamDisplayParticipantNameDirective} |
|
||||||
|
* | **displayAudioDetection** | `boolean` | {@link StreamDisplayAudioDetectionDirective} |
|
||||||
|
* | **settingsButton** | `boolean` | {@link StreamSettingsButtonDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link ApiDirectiveModule API Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
* <div>
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The StreamComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovStream** | {@link StreamDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-stream',
|
selector: 'ov-stream',
|
||||||
templateUrl: './stream.component.html',
|
templateUrl: './stream.component.html',
|
||||||
styleUrls: ['./stream.component.css']
|
styleUrls: ['./stream.component.css']
|
||||||
})
|
})
|
||||||
export class StreamComponent implements OnInit {
|
export class StreamComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ViewChild(MatMenuTrigger) public menuTrigger: MatMenuTrigger;
|
@ViewChild(MatMenuTrigger) public menuTrigger: MatMenuTrigger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ViewChild('menu') menu: MatMenuPanel;
|
@ViewChild('menu') menu: MatMenuPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
videoSizeIconEnum = VideoSizeIcon;
|
videoSizeIconEnum = VideoSizeIcon;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
videoTypeEnum = VideoType;
|
videoTypeEnum = VideoType;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
videoSizeIcon: VideoSizeIcon = VideoSizeIcon.BIG;
|
videoSizeIcon: VideoSizeIcon = VideoSizeIcon.BIG;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleNickname: boolean;
|
toggleNickname: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
_stream: StreamModel;
|
_stream: StreamModel;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
nickname: string;
|
nickname: string;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isMinimal: boolean = false;
|
isMinimal: boolean = false;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showNickname: boolean = true;
|
showNickname: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showAudioDetection: boolean = true;
|
showAudioDetection: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showSettingsButton: boolean = true;
|
showSettingsButton: boolean = true;
|
||||||
|
|
||||||
private _streamContainer: ElementRef;
|
/**
|
||||||
|
* @ignore
|
||||||
private minimalSub: Subscription;
|
*/
|
||||||
private displayParticipantNameSub: Subscription;
|
|
||||||
private displayAudioDetectionSub: Subscription;
|
|
||||||
private settingsButtonSub: Subscription;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
protected documentService: DocumentService,
|
|
||||||
protected openviduService: OpenViduService,
|
|
||||||
protected layoutService: LayoutService,
|
|
||||||
protected participantService: ParticipantService,
|
|
||||||
protected storageService: StorageService,
|
|
||||||
protected cdkSrv: CdkOverlayService,
|
|
||||||
private libService: OpenViduAngularConfigService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@ViewChild('streamContainer', { static: false, read: ElementRef })
|
@ViewChild('streamContainer', { static: false, read: ElementRef })
|
||||||
set streamContainer(streamContainer: ElementRef) {
|
set streamContainer(streamContainer: ElementRef) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -73,6 +134,9 @@ export class StreamComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ViewChild('nicknameInput')
|
@ViewChild('nicknameInput')
|
||||||
set nicknameInputElement(element: ElementRef) {
|
set nicknameInputElement(element: ElementRef) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -80,6 +144,25 @@ export class StreamComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _streamContainer: ElementRef;
|
||||||
|
private minimalSub: Subscription;
|
||||||
|
private displayParticipantNameSub: Subscription;
|
||||||
|
private displayAudioDetectionSub: Subscription;
|
||||||
|
private settingsButtonSub: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
protected documentService: DocumentService,
|
||||||
|
protected openviduService: OpenViduService,
|
||||||
|
protected layoutService: LayoutService,
|
||||||
|
protected participantService: ParticipantService,
|
||||||
|
protected storageService: StorageService,
|
||||||
|
protected cdkSrv: CdkOverlayService,
|
||||||
|
private libService: OpenViduAngularConfigService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.subscribeToStreamDirectives();
|
this.subscribeToStreamDirectives();
|
||||||
}
|
}
|
||||||
|
@ -89,8 +172,12 @@ export class StreamComponent implements OnInit {
|
||||||
if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe();
|
if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe();
|
||||||
if (this.displayAudioDetectionSub) this.displayAudioDetectionSub.unsubscribe();
|
if (this.displayAudioDetectionSub) this.displayAudioDetectionSub.unsubscribe();
|
||||||
if (this.displayParticipantNameSub) this.displayParticipantNameSub.unsubscribe();
|
if (this.displayParticipantNameSub) this.displayParticipantNameSub.unsubscribe();
|
||||||
|
if (this.minimalSub) this.minimalSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleVideoEnlarged() {
|
toggleVideoEnlarged() {
|
||||||
if (!!this._stream.streamManager?.stream?.connection?.connectionId) {
|
if (!!this._stream.streamManager?.stream?.connection?.connectionId) {
|
||||||
if (this.openviduService.isMyOwnConnection(this._stream.streamManager?.stream?.connection?.connectionId)) {
|
if (this.openviduService.isMyOwnConnection(this._stream.streamManager?.stream?.connection?.connectionId)) {
|
||||||
|
@ -102,6 +189,9 @@ export class StreamComponent implements OnInit {
|
||||||
this.layoutService.update();
|
this.layoutService.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleVideoMenu(event) {
|
toggleVideoMenu(event) {
|
||||||
if (this.menuTrigger.menuOpen) {
|
if (this.menuTrigger.menuOpen) {
|
||||||
this.menuTrigger.closeMenu();
|
this.menuTrigger.closeMenu();
|
||||||
|
@ -111,16 +201,25 @@ export class StreamComponent implements OnInit {
|
||||||
this.menuTrigger.openMenu();
|
this.menuTrigger.openMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSound() {
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
toggleMuteForcibly() {
|
||||||
this._stream.participant.setMutedForcibly(!this._stream.participant.isMutedForcibly);
|
this._stream.participant.setMutedForcibly(!this._stream.participant.isMutedForcibly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleNicknameForm() {
|
toggleNicknameForm() {
|
||||||
if (this._stream.participant.local) {
|
if (this._stream.participant.local) {
|
||||||
this.toggleNickname = !this.toggleNickname;
|
this.toggleNickname = !this.toggleNickname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
updateNickname(event) {
|
updateNickname(event) {
|
||||||
if (event?.keyCode === 13 || event?.type === 'focusout') {
|
if (event?.keyCode === 13 || event?.type === 'focusout') {
|
||||||
if (!!this.nickname) {
|
if (!!this.nickname) {
|
||||||
|
@ -132,6 +231,9 @@ export class StreamComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
async replaceScreenTrack() {
|
async replaceScreenTrack() {
|
||||||
const properties: PublisherProperties = {
|
const properties: PublisherProperties = {
|
||||||
videoSource: ScreenType.SCREEN,
|
videoSource: ScreenType.SCREEN,
|
||||||
|
@ -147,7 +249,6 @@ export class StreamComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private subscribeToStreamDirectives() {
|
private subscribeToStreamDirectives() {
|
||||||
|
|
||||||
this.minimalSub = this.libService.minimalObs.subscribe((value: boolean) => {
|
this.minimalSub = this.libService.minimalObs.subscribe((value: boolean) => {
|
||||||
this.isMinimal = value;
|
this.isMinimal = value;
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,6 +29,60 @@ import { MenuType } from '../../models/menu.model';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
import { ToolbarAdditionalButtonsDirective } from '../../directives/template/openvidu-angular.directive';
|
import { ToolbarAdditionalButtonsDirective } from '../../directives/template/openvidu-angular.directive';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The **ToolbarComponent** is hosted inside of the {@link VideoconferenceComponent}.
|
||||||
|
* It is in charge of displaying the participants controlls for handling the media, panels and more videoconference features.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
* <div>
|
||||||
|
* <h3>API Directives</h3>
|
||||||
|
*
|
||||||
|
* This component allows us to show or hide certain HTML elements with the following {@link https://angular.io/guide/attribute-directives Angular attribute directives}
|
||||||
|
* with the aim of fully customizing the ToolbarComponent.
|
||||||
|
*
|
||||||
|
* | **Name** | **Type** | **Reference** |
|
||||||
|
* | :----------------------------: | :-------: | :---------------------------------------------: |
|
||||||
|
* | **screenshareButton** | `boolean` | {@link ToolbarScreenshareButtonDirective} |
|
||||||
|
* | **fullscreenButton** | `boolean` | {@link ToolbarFullscreenButtonDirective} |
|
||||||
|
* | **leaveButton** | `boolean` | {@link ToolbarLeaveButtonDirective} |
|
||||||
|
* | **chatPanelButton** | `boolean` | {@link ToolbarChatPanelButtonDirective} |
|
||||||
|
* | **participantsPanelButton** | `boolean` | {@link ToolbarParticipantsPanelButtonDirective} |
|
||||||
|
* | **displayLogo** | `boolean` | {@link ToolbarDisplayLogoDirective} |
|
||||||
|
* | **displaySessionName** | `boolean` | {@link ToolbarDisplaySessionNameDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link ApiDirectiveModule API Directives}</span>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* </div>
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
* The ToolbarComponent can be replaced with a custom component. It provides us the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* for doing this.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovToolbar** | {@link ToolbarDirective} |
|
||||||
|
*
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* It is also providing us a way to **add additional buttons** to the default toolbar.
|
||||||
|
* It will recognise the following directive in a child element.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovToolbarAdditionalButtons** | {@link ToolbarAdditionalButtonsDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-toolbar',
|
selector: 'ov-toolbar',
|
||||||
templateUrl: './toolbar.component.html',
|
templateUrl: './toolbar.component.html',
|
||||||
|
@ -36,8 +90,14 @@ import { ToolbarAdditionalButtonsDirective } from '../../directives/template/ope
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class ToolbarComponent implements OnInit, OnDestroy {
|
export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild('toolbarAdditionalButtons', { read: TemplateRef }) toolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
@ContentChild('toolbarAdditionalButtons', { read: TemplateRef }) toolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@ContentChild(ToolbarAdditionalButtonsDirective)
|
@ContentChild(ToolbarAdditionalButtonsDirective)
|
||||||
set externalAdditionalButtons(externalAdditionalButtons: ToolbarAdditionalButtonsDirective) {
|
set externalAdditionalButtons(externalAdditionalButtons: ToolbarAdditionalButtonsDirective) {
|
||||||
// This directive will has value only when ADDITIONAL BUTTONS component tagget with '*ovToolbarAdditionalButtons' directive
|
// This directive will has value only when ADDITIONAL BUTTONS component tagget with '*ovToolbarAdditionalButtons' directive
|
||||||
|
@ -55,26 +115,86 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
@Output() onParticipantsPanelButtonClicked = new EventEmitter<any>();
|
@Output() onParticipantsPanelButtonClicked = new EventEmitter<any>();
|
||||||
@Output() onChatPanelButtonClicked = new EventEmitter<any>();
|
@Output() onChatPanelButtonClicked = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
session: Session;
|
session: Session;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
unreadMessages: number = 0;
|
unreadMessages: number = 0;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
messageList: ChatMessage[] = [];
|
messageList: ChatMessage[] = [];
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isScreenShareActive: boolean;
|
isScreenShareActive: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isWebcamVideoActive: boolean;
|
isWebcamVideoActive: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isWebcamAudioActive: boolean;
|
isWebcamAudioActive: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isConnectionLost: boolean;
|
isConnectionLost: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
hasVideoDevices: boolean;
|
hasVideoDevices: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
hasAudioDevices: boolean;
|
hasAudioDevices: boolean;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isFullscreenActive: boolean = false;
|
isFullscreenActive: boolean = false;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isChatOpened: boolean = false;
|
isChatOpened: boolean = false;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isParticipantsOpened: boolean = false;
|
isParticipantsOpened: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
isMinimal: boolean = false;
|
isMinimal: boolean = false;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showScreenshareButton = true;
|
showScreenshareButton = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showFullscreenButton: boolean = true;
|
showFullscreenButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showLeaveButton: boolean = true;
|
showLeaveButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showParticipantsPanelButton: boolean = true;
|
showParticipantsPanelButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showChatPanelButton: boolean = true;
|
showChatPanelButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showLogo: boolean = true;
|
showLogo: boolean = true;
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
showSessionName: boolean = true;
|
showSessionName: boolean = true;
|
||||||
|
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
@ -91,25 +211,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
private displaySessionNameSub: Subscription;
|
private displaySessionNameSub: Subscription;
|
||||||
private currentWindowHeight = window.innerHeight;
|
private currentWindowHeight = window.innerHeight;
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
/**
|
||||||
sizeChange(event) {
|
* @ignore
|
||||||
if (this.currentWindowHeight >= window.innerHeight) {
|
*/
|
||||||
// The user has exit the fullscreen mode
|
|
||||||
this.isFullscreenActive = false;
|
|
||||||
this.currentWindowHeight = window.innerHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('document:keydown', ['$event'])
|
|
||||||
keyDown(event: KeyboardEvent) {
|
|
||||||
if (event.key === 'F11') {
|
|
||||||
event.preventDefault();
|
|
||||||
this.toggleFullscreen();
|
|
||||||
this.currentWindowHeight = window.innerHeight;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected documentService: DocumentService,
|
protected documentService: DocumentService,
|
||||||
protected chatService: ChatService,
|
protected chatService: ChatService,
|
||||||
|
@ -125,6 +229,30 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('ToolbarComponent');
|
this.log = this.loggerSrv.get('ToolbarComponent');
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
sizeChange(event) {
|
||||||
|
if (this.currentWindowHeight >= window.innerHeight) {
|
||||||
|
// The user has exit the fullscreen mode
|
||||||
|
this.isFullscreenActive = false;
|
||||||
|
this.currentWindowHeight = window.innerHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
@HostListener('document:keydown', ['$event'])
|
||||||
|
keyDown(event: KeyboardEvent) {
|
||||||
|
if (event.key === 'F11') {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleFullscreen();
|
||||||
|
this.currentWindowHeight = window.innerHeight;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.subscribeToToolbarDirectives();
|
this.subscribeToToolbarDirectives();
|
||||||
|
@ -151,8 +279,12 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
if (this.chatPanelButtonSub) this.chatPanelButtonSub.unsubscribe();
|
if (this.chatPanelButtonSub) this.chatPanelButtonSub.unsubscribe();
|
||||||
if (this.displayLogoSub) this.displayLogoSub.unsubscribe();
|
if (this.displayLogoSub) this.displayLogoSub.unsubscribe();
|
||||||
if (this.displaySessionNameSub) this.displaySessionNameSub.unsubscribe();
|
if (this.displaySessionNameSub) this.displaySessionNameSub.unsubscribe();
|
||||||
|
if (this.minimalSub) this.minimalSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleMicrophone() {
|
toggleMicrophone() {
|
||||||
this.onMicrophoneButtonClicked.emit();
|
this.onMicrophoneButtonClicked.emit();
|
||||||
|
|
||||||
|
@ -166,6 +298,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive());
|
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
async toggleCamera() {
|
async toggleCamera() {
|
||||||
this.onCameraButtonClicked.emit();
|
this.onCameraButtonClicked.emit();
|
||||||
|
|
||||||
|
@ -200,6 +335,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
async toggleScreenShare() {
|
async toggleScreenShare() {
|
||||||
this.onScreenshareButtonClicked.emit();
|
this.onScreenshareButtonClicked.emit();
|
||||||
|
|
||||||
|
@ -277,22 +415,34 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
leaveSession() {
|
leaveSession() {
|
||||||
this.log.d('Leaving session...');
|
this.log.d('Leaving session...');
|
||||||
this.openviduService.disconnect();
|
this.openviduService.disconnect();
|
||||||
this.onLeaveButtonClicked.emit();
|
this.onLeaveButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleParticipantsPanel() {
|
toggleParticipantsPanel() {
|
||||||
this.onParticipantsPanelButtonClicked.emit();
|
this.onParticipantsPanelButtonClicked.emit();
|
||||||
this.menuService.toggleMenu(MenuType.PARTICIPANTS);
|
this.menuService.toggleMenu(MenuType.PARTICIPANTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleChatPanel() {
|
toggleChatPanel() {
|
||||||
this.onChatPanelButtonClicked.emit();
|
this.onChatPanelButtonClicked.emit();
|
||||||
this.menuService.toggleMenu(MenuType.CHAT);
|
this.menuService.toggleMenu(MenuType.CHAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
toggleFullscreen() {
|
toggleFullscreen() {
|
||||||
this.isFullscreenActive = !this.isFullscreenActive;
|
this.isFullscreenActive = !this.isFullscreenActive;
|
||||||
this.documentService.toggleFullscreen('session-container');
|
this.documentService.toggleFullscreen('session-container');
|
||||||
|
|
|
@ -19,6 +19,9 @@ import { ActionService } from '../../services/action/action.service';
|
||||||
import { ParticipantService } from '../../services/participant/participant.service';
|
import { ParticipantService } from '../../services/participant/participant.service';
|
||||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-user-settings',
|
selector: 'ov-user-settings',
|
||||||
templateUrl: './user-settings.component.html',
|
templateUrl: './user-settings.component.html',
|
||||||
|
|
|
@ -2,6 +2,9 @@ import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular
|
||||||
import { StreamManager } from 'openvidu-browser';
|
import { StreamManager } from 'openvidu-browser';
|
||||||
import { VideoType } from '../../models/video-type.model';
|
import { VideoType } from '../../models/video-type.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-video',
|
selector: 'ov-video',
|
||||||
template: `
|
template: `
|
||||||
|
|
|
@ -48,12 +48,10 @@
|
||||||
(onParticipantsPanelButtonClicked)="onParticipantsPanelButtonClicked()"
|
(onParticipantsPanelButtonClicked)="onParticipantsPanelButtonClicked()"
|
||||||
(onChatPanelButtonClicked)="onChatPanelButtonClicked()"
|
(onChatPanelButtonClicked)="onChatPanelButtonClicked()"
|
||||||
>
|
>
|
||||||
|
<ng-template #toolbarAdditionalButtons>
|
||||||
<ng-template #toolbarAdditionalButtons>
|
<ng-container *ngTemplateOutlet="openviduAngularToolbarAdditionalButtonsTemplate"></ng-container>
|
||||||
<ng-container *ngTemplateOutlet="openviduAngularToolbarAdditionalButtonsTemplate"></ng-container>
|
</ng-template>
|
||||||
</ng-template>
|
</ov-toolbar>
|
||||||
|
|
||||||
</ov-toolbar>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #defaultPanel>
|
<ng-template #defaultPanel>
|
||||||
|
@ -84,11 +82,11 @@
|
||||||
|
|
||||||
<ng-template #defaultParticipantPanelItem let-participant>
|
<ng-template #defaultParticipantPanelItem let-participant>
|
||||||
<ov-participant-panel-item [participant]="participant" id="default-participant-panel-item">
|
<ov-participant-panel-item [participant]="participant" id="default-participant-panel-item">
|
||||||
|
|
||||||
<ng-template #participantPanelItemElements>
|
<ng-template #participantPanelItemElements>
|
||||||
<ng-container *ngTemplateOutlet="openviduAngularParticipantPanelItemElementsTemplate; context: { $implicit: participant }"></ng-container>
|
<ng-container
|
||||||
|
*ngTemplateOutlet="openviduAngularParticipantPanelItemElementsTemplate; context: { $implicit: participant }"
|
||||||
|
></ng-container>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
</ov-participant-panel-item>
|
</ov-participant-panel-item>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
} from '../../directives/template/openvidu-angular.directive';
|
} from '../../directives/template/openvidu-angular.directive';
|
||||||
import { ILogger } from '../../models/logger.model';
|
import { ILogger } from '../../models/logger.model';
|
||||||
import { ParticipantProperties } from '../../models/participant.model';
|
import { ParticipantProperties } from '../../models/participant.model';
|
||||||
|
import { TokenModel } from '../../models/token.model';
|
||||||
import { ActionService } from '../../services/action/action.service';
|
import { ActionService } from '../../services/action/action.service';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
import { DeviceService } from '../../services/device/device.service';
|
import { DeviceService } from '../../services/device/device.service';
|
||||||
|
@ -34,6 +35,68 @@ import { ParticipantService } from '../../services/participant/participant.servi
|
||||||
import { StorageService } from '../../services/storage/storage.service';
|
import { StorageService } from '../../services/storage/storage.service';
|
||||||
import { TokenService } from '../../services/token/token.service';
|
import { TokenService } from '../../services/token/token.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **VideoconferenceComponent** is the parent of all OpenVidu components.
|
||||||
|
* It allow us to create a modern, useful and powerful videoconference apps with ease.
|
||||||
|
*
|
||||||
|
* <div class="custom-table-container">
|
||||||
|
* <div>
|
||||||
|
* <h3>API Directives</h3>
|
||||||
|
*
|
||||||
|
* This component allows us to show or hide certain HTML elements with the following {@link https://angular.io/guide/attribute-directives Angular attribute directives}
|
||||||
|
* with the aim of fully customizing the videoconference application.
|
||||||
|
*
|
||||||
|
* | **Parameter** | **Type** | **Reference** |
|
||||||
|
* | :----------------------------: | :-------: | :---------------------------------------------: |
|
||||||
|
* | **minimal** | `boolean` | {@link MinimalDirective} |
|
||||||
|
* | **prejoin** | `boolean` | {@link PrejoinDirective} |
|
||||||
|
* | **participantName** | `string` | {@link ParticipantNameDirective} |
|
||||||
|
* | **videoMuted** | `boolean` | {@link VideoMutedDirective} |
|
||||||
|
* | **audioMuted** | `boolean` | {@link AudioMutedDirective} |
|
||||||
|
* | **toolbarScreenshareButton** | `boolean` | {@link ToolbarScreenshareButtonDirective} |
|
||||||
|
* | **toolbarFullscreenButton** | `boolean` | {@link ToolbarFullscreenButtonDirective} |
|
||||||
|
* | **toolbarLeaveButton** | `boolean` | {@link ToolbarLeaveButtonDirective} |
|
||||||
|
* | **toolbarChatPanelButton** | `boolean` | {@link ToolbarChatPanelButtonDirective} |
|
||||||
|
* | **toolbarParticipantsPanelButton** | `boolean` | {@link ToolbarParticipantsPanelButtonDirective} |
|
||||||
|
* | **toolbarDisplayLogo** | `boolean` | {@link ToolbarDisplayLogoDirective} |
|
||||||
|
* | **toolbarDisplaySessionName** | `boolean` | {@link ToolbarDisplaySessionNameDirective} |
|
||||||
|
* | **streamDisplayParticipantName** | `boolean` | {@link StreamDisplayParticipantNameDirective} |
|
||||||
|
* | **streamDisplayAudioDetection** | `boolean` | {@link StreamDisplayAudioDetectionDirective} |
|
||||||
|
* | **streamSettingsButton** | `boolean` | {@link StreamSettingsButtonDirective} |
|
||||||
|
* | **participantPanelItemMuteButton** | `boolean` | {@link ParticipantPanelItemMuteButtonDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link ApiDirectiveModule API Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
* <div>
|
||||||
|
*
|
||||||
|
* <h3>OpenVidu Angular Directives</h3>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The VideoconferenceComponent is also providing us a way to **replace the default templates** with a custom one.
|
||||||
|
* It will recognise the following {@link https://angular.io/guide/structural-directives Angular structural directives}
|
||||||
|
* in the elements added as children.
|
||||||
|
*
|
||||||
|
* | **Directive** | **Reference** |
|
||||||
|
* |:----------------------------------:|:---------------------------------------------:|
|
||||||
|
* | ***ovToolbar** | {@link ToolbarDirective} |
|
||||||
|
* | ***ovToolbarAdditionalButtons** | {@link ToolbarAdditionalButtonsDirective} |
|
||||||
|
* | ***ovPanel** | {@link PanelDirective} |
|
||||||
|
* | ***ovChatPanel** | {@link ChatPanelDirective} |
|
||||||
|
* | ***ovParticipantsPanel** | {@link ParticipantsPanelDirective} |
|
||||||
|
* | ***ovParticipantPanelItem** | {@link ParticipantPanelItemDirective} |
|
||||||
|
* | ***ovParticipantPanelItemElements** | {@link ParticipantPanelItemElementsDirective} |
|
||||||
|
* | ***ovLayout** | {@link LayoutDirective} |
|
||||||
|
* | ***ovStream** | {@link StreamDirective} |
|
||||||
|
*
|
||||||
|
* <p class="component-link-text">
|
||||||
|
* <span class="italic">See all {@link OpenViduAngularDirectiveModule OpenVidu Angular Directives}</span>
|
||||||
|
* </p>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-videoconference',
|
selector: 'ov-videoconference',
|
||||||
templateUrl: './videoconference.component.html',
|
templateUrl: './videoconference.component.html',
|
||||||
|
@ -41,40 +104,124 @@ import { TokenService } from '../../services/token/token.service';
|
||||||
})
|
})
|
||||||
export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewInit {
|
export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
// *** Toolbar ***
|
// *** Toolbar ***
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ToolbarDirective) externalToolbar: ToolbarDirective;
|
@ContentChild(ToolbarDirective) externalToolbar: ToolbarDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ToolbarAdditionalButtonsDirective) externalToolbarAdditionalButtons: ToolbarAdditionalButtonsDirective;
|
@ContentChild(ToolbarAdditionalButtonsDirective) externalToolbarAdditionalButtons: ToolbarAdditionalButtonsDirective;
|
||||||
|
|
||||||
// *** Panels ***
|
// *** Panels ***
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(PanelDirective) externalPanel: PanelDirective;
|
@ContentChild(PanelDirective) externalPanel: PanelDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ChatPanelDirective) externalChatPanel: ChatPanelDirective;
|
@ContentChild(ChatPanelDirective) externalChatPanel: ChatPanelDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ParticipantsPanelDirective) externalParticipantsPanel: ParticipantsPanelDirective;
|
@ContentChild(ParticipantsPanelDirective) externalParticipantsPanel: ParticipantsPanelDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ParticipantPanelItemDirective) externalParticipantPanelItem: ParticipantPanelItemDirective;
|
@ContentChild(ParticipantPanelItemDirective) externalParticipantPanelItem: ParticipantPanelItemDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(ParticipantPanelItemElementsDirective) externalParticipantPanelItemElements: ParticipantPanelItemElementsDirective;
|
@ContentChild(ParticipantPanelItemElementsDirective) externalParticipantPanelItemElements: ParticipantPanelItemElementsDirective;
|
||||||
|
|
||||||
// *** Layout ***
|
// *** Layout ***
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(LayoutDirective) externalLayout: LayoutDirective;
|
@ContentChild(LayoutDirective) externalLayout: LayoutDirective;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ContentChild(StreamDirective) externalStream: StreamDirective;
|
@ContentChild(StreamDirective) externalStream: StreamDirective;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultToolbar', { static: false, read: TemplateRef }) defaultToolbarTemplate: TemplateRef<any>;
|
@ViewChild('defaultToolbar', { static: false, read: TemplateRef }) defaultToolbarTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultPanel', { static: false, read: TemplateRef }) defaultPanelTemplate: TemplateRef<any>;
|
@ViewChild('defaultPanel', { static: false, read: TemplateRef }) defaultPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultChatPanel', { static: false, read: TemplateRef }) defaultChatPanelTemplate: TemplateRef<any>;
|
@ViewChild('defaultChatPanel', { static: false, read: TemplateRef }) defaultChatPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultParticipantsPanel', { static: false, read: TemplateRef }) defaultParticipantsPanelTemplate: TemplateRef<any>;
|
@ViewChild('defaultParticipantsPanel', { static: false, read: TemplateRef }) defaultParticipantsPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultParticipantPanelItem', { static: false, read: TemplateRef }) defaultParticipantPanelItemTemplate: TemplateRef<any>;
|
@ViewChild('defaultParticipantPanelItem', { static: false, read: TemplateRef }) defaultParticipantPanelItemTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultLayout', { static: false, read: TemplateRef }) defaultLayoutTemplate: TemplateRef<any>;
|
@ViewChild('defaultLayout', { static: false, read: TemplateRef }) defaultLayoutTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@ViewChild('defaultStream', { static: false, read: TemplateRef }) defaultStreamTemplate: TemplateRef<any>;
|
@ViewChild('defaultStream', { static: false, read: TemplateRef }) defaultStreamTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularToolbarTemplate: TemplateRef<any>;
|
openviduAngularToolbarTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularToolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
openviduAngularToolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularPanelTemplate: TemplateRef<any>;
|
openviduAngularPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularChatPanelTemplate: TemplateRef<any>;
|
openviduAngularChatPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularParticipantsPanelTemplate: TemplateRef<any>;
|
openviduAngularParticipantsPanelTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularParticipantPanelItemTemplate: TemplateRef<any>;
|
openviduAngularParticipantPanelItemTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularParticipantPanelItemElementsTemplate: TemplateRef<any>;
|
openviduAngularParticipantPanelItemElementsTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularLayoutTemplate: TemplateRef<any>;
|
openviduAngularLayoutTemplate: TemplateRef<any>;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
openviduAngularStreamTemplate: TemplateRef<any>;
|
openviduAngularStreamTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
|
// *** Parameters ***
|
||||||
|
// @Input() sessionName: string;
|
||||||
|
// @Input() participantName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {TokenModel} tokens The tokens parameter must be an object with `webcam` and `screen` fields.
|
||||||
|
* Both of them are `string` type. See {@link TokenModel}
|
||||||
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
set tokens(tokens: { webcam: string; screen: string }) {
|
set tokens(tokens: TokenModel) {
|
||||||
if (!tokens || (!tokens.webcam && !tokens.screen)) {
|
if (!tokens || (!tokens.webcam && !tokens.screen)) {
|
||||||
//No tokens received
|
//No tokens received
|
||||||
// throw new Error('No tokens received');
|
// throw new Error('No tokens received');
|
||||||
|
@ -109,18 +256,38 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
||||||
// Event sent when participant has been created
|
// Event sent when participant has been created
|
||||||
@Output() onParticipantCreated = new EventEmitter<any>();
|
@Output() onParticipantCreated = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
joinSessionClicked: boolean = false;
|
joinSessionClicked: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
participantReady: boolean = false;
|
participantReady: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
canPublish: boolean = false;
|
canPublish: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
error: boolean = false;
|
error: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
errorMessage: string = '';
|
errorMessage: string = '';
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
showPrejoin: boolean = true;
|
showPrejoin: boolean = true;
|
||||||
private externalParticipantName: string;
|
private externalParticipantName: string;
|
||||||
private prejoinSub: Subscription;
|
private prejoinSub: Subscription;
|
||||||
private participantNameSub: Subscription;
|
private participantNameSub: Subscription;
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private loggerSrv: LoggerService,
|
private loggerSrv: LoggerService,
|
||||||
private storageSrv: StorageService,
|
private storageSrv: StorageService,
|
||||||
|
@ -174,6 +341,9 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
||||||
if (this.participantNameSub) this.participantNameSub.unsubscribe();
|
if (this.participantNameSub) this.participantNameSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
if (this.externalToolbar) {
|
if (this.externalToolbar) {
|
||||||
this.openviduAngularToolbarTemplate = this.externalToolbar.template;
|
this.openviduAngularToolbarTemplate = this.externalToolbar.template;
|
||||||
|
@ -239,34 +409,60 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onJoinButtonClicked() {
|
_onJoinButtonClicked() {
|
||||||
this.joinSessionClicked = true;
|
this.joinSessionClicked = true;
|
||||||
this.onJoinButtonClicked.emit();
|
this.onJoinButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onLeaveButtonClicked() {
|
onLeaveButtonClicked() {
|
||||||
this.joinSessionClicked = false;
|
this.joinSessionClicked = false;
|
||||||
this.participantReady = false;
|
this.participantReady = false;
|
||||||
this.onToolbarLeaveButtonClicked.emit();
|
this.onToolbarLeaveButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onCameraButtonClicked() {
|
onCameraButtonClicked() {
|
||||||
this.onToolbarCameraButtonClicked.emit();
|
this.onToolbarCameraButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onMicrophoneButtonClicked() {
|
onMicrophoneButtonClicked() {
|
||||||
this.onToolbarMicrophoneButtonClicked.emit();
|
this.onToolbarMicrophoneButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onScreenshareButtonClicked() {
|
onScreenshareButtonClicked() {
|
||||||
this.onToolbarScreenshareButtonClicked.emit();
|
this.onToolbarScreenshareButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onFullscreenButtonClicked() {
|
onFullscreenButtonClicked() {
|
||||||
this.onToolbarFullscreenButtonClicked.emit();
|
this.onToolbarFullscreenButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onParticipantsPanelButtonClicked() {
|
onParticipantsPanelButtonClicked() {
|
||||||
this.onToolbarParticipantsPanelButtonClicked.emit();
|
this.onToolbarParticipantsPanelButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
onChatPanelButtonClicked() {
|
onChatPanelButtonClicked() {
|
||||||
this.onToolbarChatPanelButtonClicked.emit();
|
this.onToolbarChatPanelButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onSessionCreated(event: Session) {
|
_onSessionCreated(event: Session) {
|
||||||
this.onSessionCreated.emit(event);
|
this.onSessionCreated.emit(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
ParticipantNameDirective
|
ParticipantNameDirective
|
||||||
} from './videoconference.directive';
|
} from './videoconference.directive';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
MinimalDirective,
|
MinimalDirective,
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
import { Directive, AfterViewInit, OnDestroy, Input, ElementRef } from '@angular/core';
|
import { Directive, AfterViewInit, OnDestroy, Input, ElementRef } from '@angular/core';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **muteButton** directive allows show/hide the muted button in participant panel item component.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `participantPanelItem` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [participantPanelItemMuteButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ParticipantPanelItemComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-participant-panel-item [muteButton]="false"></ov-participant-panel-item>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[participantPanelItemMuteButton], ov-participant-panel-item[muteButton]'
|
selector: 'ov-videoconference[participantPanelItemMuteButton], ov-participant-panel-item[muteButton]'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core';
|
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **displayParticipantName** directive allows show/hide the participants name in stream component.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `stream` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [streamDisplayParticipantName]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link StreamComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-stream [displayParticipantName]="false"></ov-stream>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[streamDisplayParticipantName], ov-stream[displayParticipantName]'
|
selector: 'ov-videoconference[streamDisplayParticipantName], ov-stream[displayParticipantName]'
|
||||||
})
|
})
|
||||||
|
@ -37,6 +52,21 @@ export class StreamDisplayParticipantNameDirective implements AfterViewInit, OnD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **displayAudioDetection** directive allows show/hide the participants audio detection in stream component.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `stream` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [streamDisplayAudioDetection]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link StreamComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-stream [displayAudioDetection]="false"></ov-stream>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[streamDisplayAudioDetection], ov-stream[displayAudioDetection]'
|
selector: 'ov-videoconference[streamDisplayAudioDetection], ov-stream[displayAudioDetection]'
|
||||||
})
|
})
|
||||||
|
@ -71,6 +101,21 @@ export class StreamDisplayAudioDetectionDirective implements AfterViewInit, OnDe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **settingsButton** directive allows show/hide the participants settings button in stream component.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `stream` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [streamSettingsButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link StreamComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-stream [settingsButton]="false"></ov-stream>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[streamSettingsButton], ov-stream[settingsButton]'
|
selector: 'ov-videoconference[streamSettingsButton], ov-stream[settingsButton]'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,21 +1,46 @@
|
||||||
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
|
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **screenshareButton** directive allows show/hide the screenshare toolbar button.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarScreenshareButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [screenshareButton]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarScreenshareButton], ov-toolbar[screenshareButton]'
|
selector: 'ov-videoconference[toolbarScreenshareButton], ov-toolbar[screenshareButton]'
|
||||||
})
|
})
|
||||||
export class ToolbarScreenshareButtonDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarScreenshareButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarScreenshareButton(value: boolean) {
|
@Input() set toolbarScreenshareButton(value: boolean) {
|
||||||
this.screenshareValue = value;
|
this.screenshareValue = value;
|
||||||
this.update(this.screenshareValue);
|
this.update(this.screenshareValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set screenshareButton(value: boolean) {
|
@Input() set screenshareButton(value: boolean) {
|
||||||
this.screenshareValue = value;
|
this.screenshareValue = value;
|
||||||
this.update(this.screenshareValue);
|
this.update(this.screenshareValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
screenshareValue: boolean = true;
|
private screenshareValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -25,33 +50,58 @@ export class ToolbarScreenshareButtonDirective implements AfterViewInit, OnDestr
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
|
||||||
|
private clear() {
|
||||||
this.screenshareValue = true;
|
this.screenshareValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.screenshareButton.getValue() !== value) {
|
if (this.libService.screenshareButton.getValue() !== value) {
|
||||||
this.libService.screenshareButton.next(value);
|
this.libService.screenshareButton.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **fullscreenButton** directive allows show/hide the fullscreen toolbar button.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarFullscreenButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [fullscreenButton]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarFullscreenButton], ov-toolbar[fullscreenButton]'
|
selector: 'ov-videoconference[toolbarFullscreenButton], ov-toolbar[fullscreenButton]'
|
||||||
})
|
})
|
||||||
export class ToolbarFullscreenButtonDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarFullscreenButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarFullscreenButton(value: boolean) {
|
@Input() set toolbarFullscreenButton(value: boolean) {
|
||||||
this.fullscreenValue = value;
|
this.fullscreenValue = value;
|
||||||
this.update(this.fullscreenValue);
|
this.update(this.fullscreenValue);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set fullscreenButton(value: boolean) {
|
@Input() set fullscreenButton(value: boolean) {
|
||||||
this.fullscreenValue = value;
|
this.fullscreenValue = value;
|
||||||
this.update(this.fullscreenValue);
|
this.update(this.fullscreenValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
fullscreenValue: boolean = true;
|
private fullscreenValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -60,33 +110,57 @@ export class ToolbarFullscreenButtonDirective implements AfterViewInit, OnDestro
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.fullscreenValue = true;
|
this.fullscreenValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.fullscreenButton.getValue() !== value) {
|
if (this.libService.fullscreenButton.getValue() !== value) {
|
||||||
this.libService.fullscreenButton.next(value);
|
this.libService.fullscreenButton.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **leaveButton** directive allows show/hide the leave toolbar button.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarLeaveButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [leaveButton]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarLeaveButton], ov-toolbar[leaveButton]'
|
selector: 'ov-videoconference[toolbarLeaveButton], ov-toolbar[leaveButton]'
|
||||||
})
|
})
|
||||||
export class ToolbarLeaveButtonDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarLeaveButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarLeaveButton(value: boolean) {
|
@Input() set toolbarLeaveButton(value: boolean) {
|
||||||
this.leaveValue = value;
|
this.leaveValue = value;
|
||||||
this.update(this.leaveValue);
|
this.update(this.leaveValue);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set leaveButton(value: boolean) {
|
@Input() set leaveButton(value: boolean) {
|
||||||
this.leaveValue = value;
|
this.leaveValue = value;
|
||||||
this.update(this.leaveValue);
|
this.update(this.leaveValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
leaveValue: boolean = true;
|
private leaveValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -96,33 +170,58 @@ export class ToolbarLeaveButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.leaveValue = true;
|
this.leaveValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.leaveButton.getValue() !== value) {
|
if (this.libService.leaveButton.getValue() !== value) {
|
||||||
this.libService.leaveButton.next(value);
|
this.libService.leaveButton.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **participantsPanelButton** directive allows show/hide the participants panel toolbar button.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarParticipantsPanelButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [participantsPanelButton]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarParticipantsPanelButton], ov-toolbar[participantsPanelButton]'
|
selector: 'ov-videoconference[toolbarParticipantsPanelButton], ov-toolbar[participantsPanelButton]'
|
||||||
})
|
})
|
||||||
export class ToolbarParticipantsPanelButtonDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarParticipantsPanelButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarParticipantsPanelButton(value: boolean) {
|
@Input() set toolbarParticipantsPanelButton(value: boolean) {
|
||||||
this.participantsPanelValue = value;
|
this.participantsPanelValue = value;
|
||||||
this.update(this.participantsPanelValue);
|
this.update(this.participantsPanelValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set participantsPanelButton(value: boolean) {
|
@Input() set participantsPanelButton(value: boolean) {
|
||||||
this.participantsPanelValue = value;
|
this.participantsPanelValue = value;
|
||||||
this.update(this.participantsPanelValue);
|
this.update(this.participantsPanelValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
participantsPanelValue: boolean = true;
|
private participantsPanelValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -132,32 +231,56 @@ export class ToolbarParticipantsPanelButtonDirective implements AfterViewInit, O
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.participantsPanelValue = true;
|
this.participantsPanelValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.participantsPanelButton.getValue() !== value) {
|
if (this.libService.participantsPanelButton.getValue() !== value) {
|
||||||
this.libService.participantsPanelButton.next(value);
|
this.libService.participantsPanelButton.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **chatPanelButton** directive allows show/hide the chat panel toolbar button.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarChatPanelButton]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [chatPanelButton]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarChatPanelButton], ov-toolbar[chatPanelButton]'
|
selector: 'ov-videoconference[toolbarChatPanelButton], ov-toolbar[chatPanelButton]'
|
||||||
})
|
})
|
||||||
export class ToolbarChatPanelButtonDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarChatPanelButtonDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarChatPanelButton(value: boolean) {
|
@Input() set toolbarChatPanelButton(value: boolean) {
|
||||||
this.toolbarChatPanelValue = value;
|
this.toolbarChatPanelValue = value;
|
||||||
this.update(this.toolbarChatPanelValue);
|
this.update(this.toolbarChatPanelValue);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set chatPanelButton(value: boolean) {
|
@Input() set chatPanelButton(value: boolean) {
|
||||||
this.toolbarChatPanelValue = value;
|
this.toolbarChatPanelValue = value;
|
||||||
this.update(this.toolbarChatPanelValue);
|
this.update(this.toolbarChatPanelValue);
|
||||||
}
|
}
|
||||||
toolbarChatPanelValue: boolean = true;
|
private toolbarChatPanelValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -167,33 +290,57 @@ export class ToolbarChatPanelButtonDirective implements AfterViewInit, OnDestroy
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.toolbarChatPanelValue = true;
|
this.toolbarChatPanelValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.chatPanelButton.getValue() !== value) {
|
if (this.libService.chatPanelButton.getValue() !== value) {
|
||||||
this.libService.chatPanelButton.next(value);
|
this.libService.chatPanelButton.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **displaySessionName** directive allows show/hide the session name.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarDisplaySessionName]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [displaySessionName]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarDisplaySessionName], ov-toolbar[displaySessionName]'
|
selector: 'ov-videoconference[toolbarDisplaySessionName], ov-toolbar[displaySessionName]'
|
||||||
})
|
})
|
||||||
export class ToolbarDisplaySessionNameDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarDisplaySessionNameDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarDisplaySessionName(value: boolean) {
|
@Input() set toolbarDisplaySessionName(value: boolean) {
|
||||||
this.displaySessionValue = value;
|
this.displaySessionValue = value;
|
||||||
this.update(this.displaySessionValue);
|
this.update(this.displaySessionValue);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set displaySessionName(value: boolean) {
|
@Input() set displaySessionName(value: boolean) {
|
||||||
this.displaySessionValue = value;
|
this.displaySessionValue = value;
|
||||||
this.update(this.displaySessionValue);
|
this.update(this.displaySessionValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
displaySessionValue: boolean = true;
|
private displaySessionValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -203,33 +350,57 @@ export class ToolbarDisplaySessionNameDirective implements AfterViewInit, OnDest
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.displaySessionValue = true;
|
this.displaySessionValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.displaySessionName.getValue() !== value) {
|
if (this.libService.displaySessionName.getValue() !== value) {
|
||||||
this.libService.displaySessionName.next(value);
|
this.libService.displaySessionName.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **displayLogo** directive allows show/hide the branding logo.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* It can be used in the parent element {@link VideoconferenceComponent} specifying the name of the `toolbar` component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [toolbarDisplayLogo]="false"></ov-videoconference>
|
||||||
|
*
|
||||||
|
* \
|
||||||
|
* And it also can be used in the {@link ToolbarComponent}.
|
||||||
|
* @example
|
||||||
|
* <ov-toolbar [displayLogo]="false"></ov-toolbar>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[toolbarDisplayLogo], ov-toolbar[displayLogo]'
|
selector: 'ov-videoconference[toolbarDisplayLogo], ov-toolbar[displayLogo]'
|
||||||
})
|
})
|
||||||
export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set toolbarDisplayLogo(value: boolean) {
|
@Input() set toolbarDisplayLogo(value: boolean) {
|
||||||
this.displayLogoValue = value;
|
this.displayLogoValue = value;
|
||||||
this.update(this.displayLogoValue);
|
this.update(this.displayLogoValue);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set displayLogo(value: boolean) {
|
@Input() set displayLogo(value: boolean) {
|
||||||
this.displayLogoValue = value;
|
this.displayLogoValue = value;
|
||||||
this.update(this.displayLogoValue);
|
this.update(this.displayLogoValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
displayLogoValue: boolean = true;
|
private displayLogoValue: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@ -239,12 +410,12 @@ export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
clear() {
|
private clear() {
|
||||||
this.displayLogoValue = true;
|
this.displayLogoValue = true;
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(value: boolean) {
|
private update(value: boolean) {
|
||||||
if (this.libService.displayLogo.getValue() !== value) {
|
if (this.libService.displayLogo.getValue() !== value) {
|
||||||
this.libService.displayLogo.next(value);
|
this.libService.displayLogo.next(value);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +424,10 @@ export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
// * Private directives *
|
// * Private directives *
|
||||||
|
|
||||||
// Load default OpenVidu logo if custom one is not exist
|
/**
|
||||||
|
* Load default OpenVidu logo if custom one is not exist
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'img[ovLogo]'
|
selector: 'img[ovLogo]'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,21 +1,49 @@
|
||||||
import { Directive, Input, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
import { Directive, Input, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **minimal** directive applies a minimal UI hiding all controls except for cam and mic.
|
||||||
|
*
|
||||||
|
* It is only available for {@link VideoconferenceComponent}.
|
||||||
|
*
|
||||||
|
* Default: `false`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [minimal]="true"></ov-videoconference>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[minimal]'
|
selector: 'ov-videoconference[minimal]'
|
||||||
})
|
})
|
||||||
export class MinimalDirective implements OnDestroy {
|
export class MinimalDirective implements OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set minimal(value: boolean) {
|
@Input() set minimal(value: boolean) {
|
||||||
this.update(value);
|
this.update(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.update(false);
|
this.update(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
update(value: boolean) {
|
update(value: boolean) {
|
||||||
if (this.libService.minimal.getValue() !== value) {
|
if (this.libService.minimal.getValue() !== value) {
|
||||||
this.libService.minimal.next(value);
|
this.libService.minimal.next(value);
|
||||||
|
@ -23,44 +51,102 @@ export class MinimalDirective implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **participantName** directive sets the participant name. It can be useful for aplications which doesn't need the prejoin page or applications which uses the **openvidu-webcomponent**
|
||||||
|
*
|
||||||
|
* It is only available for {@link VideoconferenceComponent}.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [participantName]="'OpenVidu'"></ov-videoconference>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[participantName]'
|
selector: 'ov-videoconference[participantName]'
|
||||||
})
|
})
|
||||||
export class ParticipantNameDirective implements OnInit {
|
export class ParticipantNameDirective implements OnInit {
|
||||||
// Avoiding update participantName dynamically.
|
// Avoiding update participantName dynamically.
|
||||||
// The participantName must be updated from UI
|
// The participantName must be updated from UI
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() participantName: string;
|
@Input() participantName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.update(this.participantName);
|
this.update(this.participantName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.update('');
|
this.update('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
update(value: string) {
|
update(value: string) {
|
||||||
this.libService.participantName.next(value);
|
this.libService.participantName.next(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **prejoin** directive allows show/hide the prejoin page for selecting media devices.
|
||||||
|
*
|
||||||
|
* It is only available for {@link VideoconferenceComponent}.
|
||||||
|
*
|
||||||
|
* Default: `true`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [prejoin]="false"></ov-videoconference>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[prejoin]'
|
selector: 'ov-videoconference[prejoin]'
|
||||||
})
|
})
|
||||||
export class PrejoinDirective implements OnDestroy {
|
export class PrejoinDirective implements OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set prejoin(value: boolean) {
|
@Input() set prejoin(value: boolean) {
|
||||||
this.update(value);
|
this.update(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.update(true);
|
this.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
update(value: boolean) {
|
update(value: boolean) {
|
||||||
if (this.libService.prejoin.getValue() !== value) {
|
if (this.libService.prejoin.getValue() !== value) {
|
||||||
this.libService.prejoin.next(value);
|
this.libService.prejoin.next(value);
|
||||||
|
@ -68,20 +154,50 @@ export class PrejoinDirective implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **videoMuted** directive allows to join the session with camera muted/unmuted.
|
||||||
|
*
|
||||||
|
* It is only available for {@link VideoconferenceComponent}.
|
||||||
|
*
|
||||||
|
* Default: `false`
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [videoMuted]="true"></ov-videoconference>
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[videoMuted]'
|
selector: 'ov-videoconference[videoMuted]'
|
||||||
})
|
})
|
||||||
export class VideoMutedDirective implements OnDestroy {
|
export class VideoMutedDirective implements OnDestroy {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set videoMuted(value: boolean) {
|
@Input() set videoMuted(value: boolean) {
|
||||||
this.update(value);
|
this.update(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.update(false);
|
this.update(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
update(value: boolean) {
|
update(value: boolean) {
|
||||||
if (this.libService.videoMuted.getValue() !== value) {
|
if (this.libService.videoMuted.getValue() !== value) {
|
||||||
this.libService.videoMuted.next(value);
|
this.libService.videoMuted.next(value);
|
||||||
|
@ -89,21 +205,48 @@ export class VideoMutedDirective implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **audioMuted** directive allows to join the session with microphone muted/unmuted.
|
||||||
|
*
|
||||||
|
* It is only available for {@link VideoconferenceComponent}.
|
||||||
|
*
|
||||||
|
* Default: `false`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference [audioMuted]="true"></ov-videoconference>
|
||||||
|
*/
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'ov-videoconference[audioMuted]'
|
selector: 'ov-videoconference[audioMuted]'
|
||||||
})
|
})
|
||||||
export class AudioMutedDirective implements OnDestroy {
|
export class AudioMutedDirective implements OnDestroy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
@Input() set audioMuted(value: boolean) {
|
@Input() set audioMuted(value: boolean) {
|
||||||
this.update(value);
|
this.update(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.update(false);
|
this.update(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
update(value: boolean) {
|
update(value: boolean) {
|
||||||
if (this.libService.audioMuted.getValue() !== value) {
|
if (this.libService.audioMuted.getValue() !== value) {
|
||||||
this.libService.audioMuted.next(value);
|
this.libService.audioMuted.next(value);
|
||||||
|
|
|
@ -1,19 +1,71 @@
|
||||||
import { Directive, TemplateRef, ViewContainerRef } from '@angular/core';
|
import { Directive, TemplateRef, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ***ovToolbar** directive allows to replace the default toolbar component injecting your custom template.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <my-custom-toolbar *ovToolbar></my-custom-toolbar>
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ovToolbar]'
|
selector: '[ovToolbar]'
|
||||||
})
|
})
|
||||||
export class ToolbarDirective {
|
export class ToolbarDirective {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ***ovToolbarAdditionalButtons** directive allows to add additional buttons to the toolbar.
|
||||||
|
* There are two ways to use this directive:
|
||||||
|
*
|
||||||
|
* 1. Adding it to an element as a child of the parent element **_ov-videoconference_** {@link VideoconferenceComponent}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
* <div *ovToolbarAdditionalButtons>
|
||||||
|
* <button>Additional button</button>
|
||||||
|
* <button>Click Me</button>
|
||||||
|
* </div>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
* <br>
|
||||||
|
* 2. Adding it to an element as child of the element tagged with the {@link ToolbarDirective}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
* <my-toolbar *ovToolbar>
|
||||||
|
* <div *ovToolbarAdditionalButtons>
|
||||||
|
* <button>Additional button</button>
|
||||||
|
* <button>Click Me</button>
|
||||||
|
* </div>
|
||||||
|
* </my-toolbar>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ovToolbarAdditionalButtons]'
|
selector: '[ovToolbarAdditionalButtons]'
|
||||||
})
|
})
|
||||||
export class ToolbarAdditionalButtonsDirective {
|
export class ToolbarAdditionalButtonsDirective {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ***ovPanel** directive allows to replace the default panel component injecting your custom template.
|
||||||
|
*
|
||||||
|
* This directive is closely related to {@link ChatPanelDirective} and {@link ParticipantsPanelDirective}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* <my-custom-panel *ovPanel>
|
||||||
|
* ...
|
||||||
|
* </my-custom-panel>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ovPanel]'
|
selector: '[ovPanel]'
|
||||||
})
|
})
|
||||||
|
@ -21,6 +73,32 @@ export class PanelDirective {
|
||||||
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
constructor(public template: TemplateRef<any>, public viewContainer: ViewContainerRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ***ovChatPanel** directive allows to replace the defaultchat panel template injecting your own component.
|
||||||
|
* There are two ways to use this directive:
|
||||||
|
*
|
||||||
|
* 1. Adding it to an element as a child of the parent element **_ov-videoconference_** {@link VideoconferenceComponent}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
* <my-chat-panel *ovChatPanel></my-chat-panel>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
* <br>
|
||||||
|
* 2. Adding it to an element as child of the element tagged with the {@link ToolbarDirective}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
* <my-panel *ovPanel>
|
||||||
|
* <my-chat-panel *ovChatPanel></my-chat-panel>
|
||||||
|
* </my-panel>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
* <div class="info-container">
|
||||||
|
* <span>INFO:</span>
|
||||||
|
* You also can use the default components adsada dasda d asd
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ovChatPanel]'
|
selector: '[ovChatPanel]'
|
||||||
})
|
})
|
||||||
|
@ -56,10 +134,37 @@ export class LayoutDirective {
|
||||||
constructor(public template: TemplateRef<any>, public container: ViewContainerRef) {}
|
constructor(public template: TemplateRef<any>, public container: ViewContainerRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ***ovStream** directive allows to replace the default stream component template injecting your own component.
|
||||||
|
* There are two ways to use this directive:
|
||||||
|
*
|
||||||
|
* 1. Adding it to an element as a child of the parent element **_ov-videoconference_** {@link VideoconferenceComponent}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <my-chat-panel *ovChatPanel></my-chat-panel>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
* <br>
|
||||||
|
* 2. Adding it to an element as child of the element tagged with the {@link ToolbarDirective}
|
||||||
|
* @example
|
||||||
|
* <ov-videoconference>
|
||||||
|
* <my-panel *ovPanel>
|
||||||
|
* <my-chat-panel *ovChatPanel></my-chat-panel>
|
||||||
|
* </my-panel>
|
||||||
|
* </ov-videoconference>
|
||||||
|
*
|
||||||
|
* <div class="info-container">
|
||||||
|
* <span>INFO:</span>
|
||||||
|
* You also can use the default components adsada dasda d asd
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ovStream]'
|
selector: '[ovStream]'
|
||||||
})
|
})
|
||||||
export class StreamDirective {
|
export class StreamDirective {
|
||||||
constructor(public template: TemplateRef<any>, public container: ViewContainerRef) {}
|
constructor(public template: TemplateRef<any>, public container: ViewContainerRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
|
||||||
import { ErrorStateMatcher } from '@angular/material/core';
|
import { ErrorStateMatcher } from '@angular/material/core';
|
||||||
|
|
||||||
/** Error when invalid control is dirty, touched, or submitted. */
|
/** Error when invalid control is dirty, touched, or submitted. */
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export class NicknameMatcher implements ErrorStateMatcher {
|
export class NicknameMatcher implements ErrorStateMatcher {
|
||||||
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||||
const isSubmitted = form && form.submitted;
|
const isSubmitted = form && form.submitted;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
export enum AvatarType {
|
/**
|
||||||
DEFAULT = 'default',
|
* @internal
|
||||||
CAPTURED = 'captured'
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChatMessage {
|
export interface ChatMessage {
|
||||||
isLocal: boolean;
|
isLocal: boolean;
|
||||||
nickname: string;
|
nickname: string;
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface CustomDevice {
|
export interface CustomDevice {
|
||||||
label: string;
|
label: string;
|
||||||
device: string;
|
device: string;
|
||||||
type?: CameraType;
|
type?: CameraType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum CameraType {
|
export enum CameraType {
|
||||||
FRONT = 'FRONT',
|
FRONT = 'FRONT',
|
||||||
BACK = 'BACK'
|
BACK = 'BACK'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum DeviceType {
|
export enum DeviceType {
|
||||||
AUDIO_INPUT = 'audioinput',
|
AUDIO_INPUT = 'audioinput',
|
||||||
VIDEO_INPUT = 'videoinput'
|
VIDEO_INPUT = 'videoinput'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum VideoSizeIcon {
|
export enum VideoSizeIcon {
|
||||||
BIG = 'zoom_in',
|
BIG = 'zoom_in',
|
||||||
NORMAL = 'zoom_out'
|
NORMAL = 'zoom_out'
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum LayoutClass {
|
export enum LayoutClass {
|
||||||
ROOT_ELEMENT = 'OT_root',
|
ROOT_ELEMENT = 'OT_root',
|
||||||
BIG_ELEMENT = 'OV_big',
|
BIG_ELEMENT = 'OV_big',
|
||||||
|
@ -6,15 +9,17 @@ export enum LayoutClass {
|
||||||
NO_SIZE_ELEMENT = 'no-size'
|
NO_SIZE_ELEMENT = 'no-size'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum SidenavMode {
|
export enum SidenavMode {
|
||||||
OVER = 'over',
|
OVER = 'over',
|
||||||
SIDE = 'side'
|
SIDE = 'side'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface OpenViduLayoutOptions {
|
export interface OpenViduLayoutOptions {
|
||||||
/**
|
/**
|
||||||
* The narrowest ratio that will be used (*2x3* by default)
|
* The narrowest ratio that will be used (*2x3* by default)
|
||||||
|
@ -70,6 +75,9 @@ export interface OpenViduLayoutOptions {
|
||||||
bigFirst: any;
|
bigFirst: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export class OpenViduLayout {
|
export class OpenViduLayout {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { Autolinker, AutolinkerConfig, HashtagMatch } from 'autolinker';
|
import { Autolinker, AutolinkerConfig, HashtagMatch } from 'autolinker';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
const AUTOLINKER_CFGS: AutolinkerConfig = {
|
const AUTOLINKER_CFGS: AutolinkerConfig = {
|
||||||
urls: {
|
urls: {
|
||||||
schemeMatches: true,
|
schemeMatches: true,
|
||||||
|
@ -20,6 +23,9 @@ const AUTOLINKER_CFGS: AutolinkerConfig = {
|
||||||
decodePercentEncoding: true
|
decodePercentEncoding: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export class Linkifier {
|
export class Linkifier {
|
||||||
private autolinker: Autolinker;
|
private autolinker: Autolinker;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface ILogger {
|
export interface ILogger {
|
||||||
d(...args: any[]): void;
|
d(...args: any[]): void;
|
||||||
w(...args: any[]): void;
|
w(...args: any[]): void;
|
||||||
e(...args: any[]): void;
|
e(...args: any[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface ILogService {
|
export interface ILogService {
|
||||||
get(name: string): ILogger;
|
get(name: string): ILogger;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum MenuType {
|
export enum MenuType {
|
||||||
CHAT = 'chat',
|
CHAT = 'chat',
|
||||||
PARTICIPANTS = 'participants'
|
PARTICIPANTS = 'participants'
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { MatSnackBarConfig } from '@angular/material/snack-bar';
|
import { MatSnackBarConfig } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface INotificationOptions {
|
export interface INotificationOptions {
|
||||||
message: string;
|
message: string;
|
||||||
buttonActionText?: string;
|
buttonActionText?: string;
|
||||||
|
|
|
@ -2,19 +2,52 @@ import { Publisher, StreamManager } from 'openvidu-browser';
|
||||||
import { VideoType } from './video-type.model';
|
import { VideoType } from './video-type.model';
|
||||||
|
|
||||||
export interface StreamModel {
|
export interface StreamModel {
|
||||||
|
/**
|
||||||
|
* Whether the stream is available or not
|
||||||
|
*/
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
|
/**
|
||||||
|
* The stream type.{@link VideoType}
|
||||||
|
*/
|
||||||
type: VideoType;
|
type: VideoType;
|
||||||
|
/**
|
||||||
|
* The streamManager object from openvidu-browser library.{@link https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/StreamManager.html}
|
||||||
|
*/
|
||||||
streamManager: StreamManager;
|
streamManager: StreamManager;
|
||||||
|
/**
|
||||||
|
* Whether the stream is enlarged or not
|
||||||
|
*/
|
||||||
videoEnlarged: boolean;
|
videoEnlarged: boolean;
|
||||||
|
/**
|
||||||
|
* Unique identifier of the stream
|
||||||
|
*/
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
participant?: ParticipantAbstractModel
|
/**
|
||||||
|
* The participant object
|
||||||
|
*/
|
||||||
|
participant?: ParticipantAbstractModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ParticipantProperties {
|
export interface ParticipantProperties {
|
||||||
|
/**
|
||||||
|
* Whether the participant is local or not
|
||||||
|
*/
|
||||||
local: boolean;
|
local: boolean;
|
||||||
|
/**
|
||||||
|
* The participant nickname
|
||||||
|
*/
|
||||||
nickname: string;
|
nickname: string;
|
||||||
|
/**
|
||||||
|
* Unique identifier of the participant
|
||||||
|
*/
|
||||||
id?: string;
|
id?: string;
|
||||||
|
/**
|
||||||
|
* The participant color profile
|
||||||
|
*/
|
||||||
colorProfile?: string;
|
colorProfile?: string;
|
||||||
|
/**
|
||||||
|
* Whether the participant is muted forcibly or not
|
||||||
|
*/
|
||||||
isMutedForcibly?: boolean;
|
isMutedForcibly?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +63,7 @@ export abstract class ParticipantAbstractModel {
|
||||||
this.id = props.id ? props.id : new Date().getTime().toString();
|
this.id = props.id ? props.id : new Date().getTime().toString();
|
||||||
this.local = props.local;
|
this.local = props.local;
|
||||||
this.nickname = props.nickname;
|
this.nickname = props.nickname;
|
||||||
this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random()*360}, 100%, 80%)`;
|
this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random() * 360}, 100%, 80%)`;
|
||||||
this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false;
|
this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false;
|
||||||
let streamModel: StreamModel = {
|
let streamModel: StreamModel = {
|
||||||
connected: model ? model.connected : true,
|
connected: model ? model.connected : true,
|
||||||
|
@ -43,43 +76,68 @@ export abstract class ParticipantAbstractModel {
|
||||||
this.streams.set(streamModel.type, streamModel);
|
this.streams.set(streamModel.type, streamModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
addConnection(streamModel: StreamModel) {
|
addConnection(streamModel: StreamModel) {
|
||||||
streamModel.participant = this;
|
streamModel.participant = this;
|
||||||
this.streams.set(streamModel.type, streamModel);
|
this.streams.set(streamModel.type, streamModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
public isCameraAudioActive(): boolean {
|
public isCameraAudioActive(): boolean {
|
||||||
const cameraConnection = this.getCameraConnection();
|
const cameraConnection = this.getCameraConnection();
|
||||||
if(cameraConnection) {
|
if (cameraConnection) {
|
||||||
return cameraConnection.connected && cameraConnection.streamManager?.stream?.audioActive;
|
return cameraConnection.connected && cameraConnection.streamManager?.stream?.audioActive;
|
||||||
}
|
}
|
||||||
return this.isScreenAudioActive();;
|
return this.isScreenAudioActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
public isCameraVideoActive(): boolean {
|
public isCameraVideoActive(): boolean {
|
||||||
const cameraConnection = this.getCameraConnection();
|
const cameraConnection = this.getCameraConnection();
|
||||||
return cameraConnection?.connected && cameraConnection?.streamManager?.stream?.videoActive;
|
return cameraConnection?.connected && cameraConnection?.streamManager?.stream?.videoActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isScreenAudioActive(): boolean {
|
isScreenAudioActive(): boolean {
|
||||||
const screenConnection = this.getScreenConnection();
|
const screenConnection = this.getScreenConnection();
|
||||||
if(screenConnection){
|
if (screenConnection) {
|
||||||
return screenConnection?.connected && screenConnection?.streamManager?.stream?.audioActive;
|
return screenConnection?.connected && screenConnection?.streamManager?.stream?.audioActive;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
hasConnectionType(type: VideoType): boolean {
|
hasConnectionType(type: VideoType): boolean {
|
||||||
return this.streams.has(type);
|
return this.streams.has(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
public getCameraConnection(): StreamModel {
|
public getCameraConnection(): StreamModel {
|
||||||
return this.streams.get(VideoType.CAMERA);
|
return this.streams.get(VideoType.CAMERA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
public getScreenConnection(): StreamModel {
|
public getScreenConnection(): StreamModel {
|
||||||
return this.streams.get(VideoType.SCREEN);
|
return this.streams.get(VideoType.SCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getConnectionTypesActive(): VideoType[] {
|
getConnectionTypesActive(): VideoType[] {
|
||||||
let connType = [];
|
let connType = [];
|
||||||
if (this.isCameraActive()) connType.push(VideoType.CAMERA);
|
if (this.isCameraActive()) connType.push(VideoType.CAMERA);
|
||||||
|
@ -88,116 +146,168 @@ export abstract class ParticipantAbstractModel {
|
||||||
return connType;
|
return connType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setCameraConnectionId(connectionId: string) {
|
setCameraConnectionId(connectionId: string) {
|
||||||
this.getCameraConnection().connectionId = connectionId;
|
this.getCameraConnection().connectionId = connectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setScreenConnectionId(connectionId: string) {
|
setScreenConnectionId(connectionId: string) {
|
||||||
this.getScreenConnection().connectionId = connectionId;
|
this.getScreenConnection().connectionId = connectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
removeConnection(connectionId: string): StreamModel {
|
removeConnection(connectionId: string): StreamModel {
|
||||||
const removeStream = this.getConnectionById(connectionId);
|
const removeStream = this.getConnectionById(connectionId);
|
||||||
this.streams.delete(removeStream.type);
|
this.streams.delete(removeStream.type);
|
||||||
return removeStream;
|
return removeStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
hasConnectionId(connectionId: string): boolean {
|
hasConnectionId(connectionId: string): boolean {
|
||||||
return Array.from(this.streams.values()).some((conn) => conn.connectionId === connectionId);
|
return Array.from(this.streams.values()).some((conn) => conn.connectionId === connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getConnectionById(connectionId: string): StreamModel {
|
getConnectionById(connectionId: string): StreamModel {
|
||||||
return Array.from(this.streams.values()).find((conn) => conn.connectionId === connectionId);
|
return Array.from(this.streams.values()).find((conn) => conn.connectionId === connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getAvailableConnections(): StreamModel[] {
|
getAvailableConnections(): StreamModel[] {
|
||||||
return Array.from(this.streams.values()).filter((conn) => conn.connected);
|
return Array.from(this.streams.values()).filter((conn) => conn.connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isLocal(): boolean {
|
isLocal(): boolean {
|
||||||
return this.local;
|
return this.local;
|
||||||
// return Array.from(this.streams.values()).every((conn) => conn.local);
|
// return Array.from(this.streams.values()).every((conn) => conn.local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setNickname(nickname: string) {
|
setNickname(nickname: string) {
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
// this.streams.forEach((conn) => {
|
|
||||||
// if (conn.type === VideoType.CAMERA) {
|
|
||||||
// conn.nickname = nickname;
|
|
||||||
// } else {
|
|
||||||
// conn.nickname = `${nickname}_${conn.type}`;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getNickname() {
|
getNickname() {
|
||||||
return this.nickname;
|
return this.nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCameraNickname(): string {
|
/**
|
||||||
// return this.getCameraConnection()?.nickname;
|
* @internal
|
||||||
// }
|
*/
|
||||||
|
|
||||||
// getScreenNickname(): string {
|
|
||||||
// return this.getScreenConnection()?.nickname;
|
|
||||||
// }
|
|
||||||
|
|
||||||
setCameraPublisher(publisher: Publisher) {
|
setCameraPublisher(publisher: Publisher) {
|
||||||
const cameraConnection = this.getCameraConnection();
|
const cameraConnection = this.getCameraConnection();
|
||||||
if (cameraConnection) cameraConnection.streamManager = publisher;
|
if (cameraConnection) cameraConnection.streamManager = publisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setScreenPublisher(publisher: Publisher) {
|
setScreenPublisher(publisher: Publisher) {
|
||||||
const screenConnection = this.getScreenConnection();
|
const screenConnection = this.getScreenConnection();
|
||||||
if (screenConnection) screenConnection.streamManager = publisher;
|
if (screenConnection) screenConnection.streamManager = publisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setPublisher(connType: VideoType, publisher: StreamManager) {
|
setPublisher(connType: VideoType, publisher: StreamManager) {
|
||||||
const connection = this.streams.get(connType);
|
const connection = this.streams.get(connType);
|
||||||
if(connection) {
|
if (connection) {
|
||||||
connection.streamManager = publisher;
|
connection.streamManager = publisher;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isCameraActive(): boolean {
|
isCameraActive(): boolean {
|
||||||
return this.getCameraConnection()?.connected;
|
return this.getCameraConnection()?.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
enableCamera() {
|
enableCamera() {
|
||||||
const cameraConnection = this.getCameraConnection();
|
const cameraConnection = this.getCameraConnection();
|
||||||
if (cameraConnection) cameraConnection.connected = true;
|
if (cameraConnection) cameraConnection.connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
disableCamera() {
|
disableCamera() {
|
||||||
const cameraConnection = this.getCameraConnection();
|
const cameraConnection = this.getCameraConnection();
|
||||||
if (cameraConnection) cameraConnection.connected = false;
|
if (cameraConnection) cameraConnection.connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isScreenActive(): boolean {
|
isScreenActive(): boolean {
|
||||||
return this.getScreenConnection()?.connected;
|
return this.getScreenConnection()?.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
enableScreen() {
|
enableScreen() {
|
||||||
const screenConnection = this.getScreenConnection();
|
const screenConnection = this.getScreenConnection();
|
||||||
if (screenConnection) screenConnection.connected = true;
|
if (screenConnection) screenConnection.connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
disableScreen() {
|
disableScreen() {
|
||||||
const screenConnection = this.getScreenConnection();
|
const screenConnection = this.getScreenConnection();
|
||||||
if (screenConnection) screenConnection.connected = false;
|
if (screenConnection) screenConnection.connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setAllVideoEnlarged(enlarged: boolean) {
|
setAllVideoEnlarged(enlarged: boolean) {
|
||||||
this.streams.forEach((conn) => (conn.videoEnlarged = enlarged));
|
this.streams.forEach((conn) => (conn.videoEnlarged = enlarged));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setCameraEnlarged(enlarged: boolean) {
|
setCameraEnlarged(enlarged: boolean) {
|
||||||
this.streams.get(VideoType.CAMERA).videoEnlarged = enlarged;
|
this.streams.get(VideoType.CAMERA).videoEnlarged = enlarged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setScreenEnlarged(enlarged: boolean) {
|
setScreenEnlarged(enlarged: boolean) {
|
||||||
this.streams.get(VideoType.SCREEN).videoEnlarged = enlarged;
|
this.streams.get(VideoType.SCREEN).videoEnlarged = enlarged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
toggleVideoEnlarged(connectionId: string) {
|
toggleVideoEnlarged(connectionId: string) {
|
||||||
this.streams.forEach((conn) => {
|
this.streams.forEach((conn) => {
|
||||||
if (conn.connectionId === connectionId) {
|
if (conn.connectionId === connectionId) {
|
||||||
|
@ -206,17 +316,22 @@ export abstract class ParticipantAbstractModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
someHasVideoEnlarged(): boolean {
|
someHasVideoEnlarged(): boolean {
|
||||||
return Array.from(this.streams.values()).some((conn) => conn.videoEnlarged);
|
return Array.from(this.streams.values()).some((conn) => conn.videoEnlarged);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMutedForcibly(muted: boolean){
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
setMutedForcibly(muted: boolean) {
|
||||||
this.isMutedForcibly = muted;
|
this.isMutedForcibly = muted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParticipantModel extends ParticipantAbstractModel {
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
}
|
export class ParticipantModel extends ParticipantAbstractModel {}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum Signal {
|
export enum Signal {
|
||||||
NICKNAME_CHANGED = 'nicknameChanged',
|
NICKNAME_CHANGED = 'nicknameChanged',
|
||||||
CHAT = 'chat'
|
CHAT = 'chat'
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum Storage{
|
export enum Storage{
|
||||||
USER_NICKNAME = 'openviduCallNickname',
|
USER_NICKNAME = 'openviduCallNickname',
|
||||||
VIDEO_DEVICE = 'openviduCallVideoDevice',
|
VIDEO_DEVICE = 'openviduCallVideoDevice',
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface TokenModel {
|
||||||
|
webcam: string;
|
||||||
|
screen: string;
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ export enum VideoType {
|
||||||
CUSTOM = 'CUSTOM'
|
CUSTOM = 'CUSTOM'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export enum ScreenType {
|
export enum ScreenType {
|
||||||
WINDOW = 'window',
|
WINDOW = 'window',
|
||||||
SCREEN = 'screen'
|
SCREEN = 'screen'
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { ISettings } from './settings.model';
|
|
||||||
|
|
||||||
export interface ISessionConfig {
|
|
||||||
sessionName: string;
|
|
||||||
user: string;
|
|
||||||
tokens: string[];
|
|
||||||
ovSettings: ISettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Theme {
|
|
||||||
DARK = 'dark',
|
|
||||||
LIGHT = 'light'
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
import { Linkifier } from '../models/linkifier.model';
|
import { Linkifier } from '../models/linkifier.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Pipe({ name: 'linkify' })
|
@Pipe({ name: 'linkify' })
|
||||||
export class LinkifyPipe implements PipeTransform {
|
export class LinkifyPipe implements PipeTransform {
|
||||||
private linkifer: Linkifier;
|
private linkifer: Linkifier;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
import { StreamModel, ParticipantAbstractModel } from '../models/participant.model';
|
import { StreamModel, ParticipantAbstractModel } from '../models/participant.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Pipe({ name: 'streams' })
|
@Pipe({ name: 'streams' })
|
||||||
export class ParticipantStreamsPipe implements PipeTransform {
|
export class ParticipantStreamsPipe implements PipeTransform {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
@ -21,6 +24,9 @@ export class ParticipantStreamsPipe implements PipeTransform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Pipe({ name: 'streamTypesEnabled' })
|
@Pipe({ name: 'streamTypesEnabled' })
|
||||||
export class StreamTypesEnabledPipe implements PipeTransform {
|
export class StreamTypesEnabledPipe implements PipeTransform {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
|
@ -5,6 +5,9 @@ import { DialogTemplateComponent } from '../../components/material/dialog.compon
|
||||||
|
|
||||||
import { INotificationOptions } from '../../models/notification-options.model';
|
import { INotificationOptions } from '../../models/notification-options.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import {CdkOverlayContainer } from '../../config/custom-cdk-overlay';
|
import {CdkOverlayContainer } from '../../config/custom-cdk-overlay';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,9 @@ import { SidenavMenuService } from '../sidenav-menu/sidenav-menu.service';
|
||||||
import { ParticipantService } from '../participant/participant.service';
|
import { ParticipantService } from '../participant/participant.service';
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../models/menu.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,9 @@ import { OpenViduAngularConfig, ParticipantFactoryFunction } from '../../config/
|
||||||
|
|
||||||
// import { version } from '../../../../package.json';
|
// import { version } from '../../../../package.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpenViduAngularConfigService {
|
export class OpenViduAngularConfigService {
|
||||||
private configuration: OpenViduAngularConfig;
|
private configuration: OpenViduAngularConfig;
|
||||||
|
@ -51,7 +53,7 @@ export class OpenViduAngularConfigService {
|
||||||
constructor(@Inject('OPENVIDU_ANGULAR_CONFIG') config: OpenViduAngularConfig) {
|
constructor(@Inject('OPENVIDU_ANGULAR_CONFIG') config: OpenViduAngularConfig) {
|
||||||
this.configuration = config;
|
this.configuration = config;
|
||||||
console.log(this.configuration);
|
console.log(this.configuration);
|
||||||
if(this.isProduction()) console.log('OpenVidu Angular Production Mode');
|
if (this.isProduction()) console.log('OpenVidu Angular Production Mode');
|
||||||
this.minimalObs = this.minimal.asObservable();
|
this.minimalObs = this.minimal.asObservable();
|
||||||
this.participantNameObs = this.participantName.asObservable();
|
this.participantNameObs = this.participantName.asObservable();
|
||||||
this.prejoinObs = this.prejoin.asObservable();
|
this.prejoinObs = this.prejoin.asObservable();
|
||||||
|
@ -85,7 +87,7 @@ export class OpenViduAngularConfigService {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
hasParticipantFactory(): boolean {
|
hasParticipantFactory(): boolean {
|
||||||
return typeof this.getConfig().participantFactory === "function";
|
return typeof this.getConfig().participantFactory === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
getParticipantFactory(): ParticipantFactoryFunction {
|
getParticipantFactory(): ParticipantFactoryFunction {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CameraType, IDevice } from '../../models/device.model';
|
import { CameraType, CustomDevice } from '../../models/device.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceServiceMock {
|
export class DeviceServiceMock {
|
||||||
audioDevice: IDevice = {
|
audioDevice: CustomDevice = {
|
||||||
label: 'audio',
|
label: 'audio',
|
||||||
device: 'mockDevice'
|
device: 'mockDevice'
|
||||||
};
|
};
|
||||||
videodevice: IDevice = {
|
videodevice: CustomDevice = {
|
||||||
label: 'video',
|
label: 'video',
|
||||||
device: 'mockDevice',
|
device: 'mockDevice',
|
||||||
type: CameraType.FRONT
|
type: CameraType.FRONT
|
||||||
|
@ -17,11 +17,11 @@ export class DeviceServiceMock {
|
||||||
|
|
||||||
async initDevices() {}
|
async initDevices() {}
|
||||||
|
|
||||||
getCamSelected(): IDevice {
|
getCamSelected(): CustomDevice {
|
||||||
return this.videodevice;
|
return this.videodevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMicSelected(): IDevice {
|
getMicSelected(): CustomDevice {
|
||||||
return this.audioDevice;
|
return this.audioDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ export class DeviceServiceMock {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCameras(): IDevice[] {
|
getCameras(): CustomDevice[] {
|
||||||
return [this.videodevice];
|
return [this.videodevice];
|
||||||
}
|
}
|
||||||
|
|
||||||
getMicrophones(): IDevice[] {
|
getMicrophones(): CustomDevice[] {
|
||||||
return [this.audioDevice];
|
return [this.audioDevice];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ import { LoggerService } from '../logger/logger.service';
|
||||||
import { PlatformService } from '../platform/platform.service';
|
import { PlatformService } from '../platform/platform.service';
|
||||||
import { StorageService } from '../storage/storage.service';
|
import { StorageService } from '../storage/storage.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
@ -60,7 +63,7 @@ export class DeviceService {
|
||||||
this.microphones = customDevices.microphones;
|
this.microphones = customDevices.microphones;
|
||||||
|
|
||||||
this._isVideoMuted = this.storageSrv.isVideoMuted() || this.libSrv.videoMuted.getValue();
|
this._isVideoMuted = this.storageSrv.isVideoMuted() || this.libSrv.videoMuted.getValue();
|
||||||
this._isAudioMuted = this.storageSrv.isAudioMuted() || this.libSrv.audioMuted.getValue();;
|
this._isAudioMuted = this.storageSrv.isAudioMuted() || this.libSrv.audioMuted.getValue();
|
||||||
|
|
||||||
this.log.d('Media devices', customDevices);
|
this.log.d('Media devices', customDevices);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { LayoutClass } from '../../models/layout.model';
|
import { LayoutClass } from '../../models/layout.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { LayoutClass, OpenViduLayout, OpenViduLayoutOptions } from '../../models/layout.model';
|
import { LayoutClass, OpenViduLayout, OpenViduLayoutOptions } from '../../models/layout.model';
|
||||||
import { DocumentService } from '../document/document.service';
|
import { DocumentService } from '../document/document.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { ILogService } from '../../models/logger.model';
|
||||||
|
|
||||||
import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.service';
|
import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,6 +33,9 @@ export class OpenViduService {
|
||||||
protected audioSource = undefined;
|
protected audioSource = undefined;
|
||||||
protected log: ILogger;
|
protected log: ILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
protected openviduAngularConfigSrv: OpenViduAngularConfigService,
|
protected openviduAngularConfigSrv: OpenViduAngularConfigService,
|
||||||
protected platformService: PlatformService,
|
protected platformService: PlatformService,
|
||||||
|
@ -43,6 +46,9 @@ export class OpenViduService {
|
||||||
this.log = this.loggerSrv.get('OpenViduService');
|
this.log = this.loggerSrv.get('OpenViduService');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
this.OV = new OpenVidu();
|
this.OV = new OpenVidu();
|
||||||
if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode();
|
if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode();
|
||||||
|
@ -60,22 +66,37 @@ export class OpenViduService {
|
||||||
return this.getWebcamSession();
|
return this.getWebcamSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getWebcamSession(): Session {
|
getWebcamSession(): Session {
|
||||||
return this.webcamSession;
|
return this.webcamSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isWebcamSessionConnected(): boolean {
|
isWebcamSessionConnected(): boolean {
|
||||||
return !!this.webcamSession.capabilities;
|
return !!this.webcamSession.capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getScreenSession(): Session {
|
getScreenSession(): Session {
|
||||||
return this.screenSession;
|
return this.screenSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isScreenSessionConnected(): boolean {
|
isScreenSessionConnected(): boolean {
|
||||||
return !!this.screenSession.capabilities;
|
return !!this.screenSession.capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
async connectSession(session: Session, token: string): Promise<void> {
|
async connectSession(session: Session, token: string): Promise<void> {
|
||||||
if (!!token && session) {
|
if (!!token && session) {
|
||||||
const nickname = this.participantService.getMyNickname();
|
const nickname = this.participantService.getMyNickname();
|
||||||
|
@ -101,6 +122,9 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
disconnect() {
|
disconnect() {
|
||||||
this.disconnectSession(this.webcamSession);
|
this.disconnectSession(this.webcamSession);
|
||||||
this.disconnectSession(this.screenSession);
|
this.disconnectSession(this.screenSession);
|
||||||
|
@ -111,6 +135,7 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
* Initialize a publisher checking devices saved on storage or if participant have devices available.
|
* Initialize a publisher checking devices saved on storage or if participant have devices available.
|
||||||
*/
|
*/
|
||||||
async initDefaultPublisher(targetElement: string | HTMLElement): Promise<Publisher> {
|
async initDefaultPublisher(targetElement: string | HTMLElement): Promise<Publisher> {
|
||||||
|
@ -158,11 +183,17 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
async initPublisher(targetElement: string | HTMLElement, properties: PublisherProperties): Promise<Publisher> {
|
async initPublisher(targetElement: string | HTMLElement, properties: PublisherProperties): Promise<Publisher> {
|
||||||
this.log.d('Initializing publisher with properties: ', properties);
|
this.log.d('Initializing publisher with properties: ', properties);
|
||||||
return await this.OV.initPublisherAsync(targetElement, properties);
|
return await this.OV.initPublisherAsync(targetElement, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
async publish(publisher: Publisher): Promise<void> {
|
async publish(publisher: Publisher): Promise<void> {
|
||||||
if (!!publisher) {
|
if (!!publisher) {
|
||||||
if (publisher === this.participantService.getMyCameraPublisher()) {
|
if (publisher === this.participantService.getMyCameraPublisher()) {
|
||||||
|
@ -179,6 +210,9 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
unpublish(publisher: Publisher): void {
|
unpublish(publisher: Publisher): void {
|
||||||
if (!!publisher) {
|
if (!!publisher) {
|
||||||
if (publisher === this.participantService.getMyCameraPublisher()) {
|
if (publisher === this.participantService.getMyCameraPublisher()) {
|
||||||
|
@ -190,6 +224,9 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
publishVideo(publisher: Publisher, value: boolean): void {
|
publishVideo(publisher: Publisher, value: boolean): void {
|
||||||
if (!!publisher) {
|
if (!!publisher) {
|
||||||
publisher.publishVideo(value);
|
publisher.publishVideo(value);
|
||||||
|
@ -197,6 +234,9 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
publishAudio(publisher: Publisher, value: boolean): void {
|
publishAudio(publisher: Publisher, value: boolean): void {
|
||||||
if (!!publisher) {
|
if (!!publisher) {
|
||||||
publisher.publishAudio(value);
|
publisher.publishAudio(value);
|
||||||
|
@ -204,8 +244,11 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this method when replaceTrack issue is fixed
|
/**
|
||||||
// https://github.com/OpenVidu/openvidu/pull/700
|
* TODO: Remove this method when replaceTrack issue is fixed
|
||||||
|
* https://github.com/OpenVidu/openvidu/pull/700
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
republishTrack(properties: PublisherProperties): Promise<void> {
|
republishTrack(properties: PublisherProperties): Promise<void> {
|
||||||
const { videoSource, audioSource, mirror } = properties;
|
const { videoSource, audioSource, mirror } = properties;
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
@ -240,6 +283,9 @@ export class OpenViduService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
sendSignal(type: Signal, connections?: Connection[], data?: any): void {
|
sendSignal(type: Signal, connections?: Connection[], data?: any): void {
|
||||||
const signalOptions: SignalOptions = {
|
const signalOptions: SignalOptions = {
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -255,6 +301,9 @@ export class OpenViduService {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
async replaceTrack(videoType: VideoType, props: PublisherProperties) {
|
async replaceTrack(videoType: VideoType, props: PublisherProperties) {
|
||||||
try {
|
try {
|
||||||
this.log.d(`Replacing ${videoType} track`, props);
|
this.log.d(`Replacing ${videoType} track`, props);
|
||||||
|
@ -346,6 +395,9 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
needSendNicknameSignal(): boolean {
|
needSendNicknameSignal(): boolean {
|
||||||
let oldNickname: string;
|
let oldNickname: string;
|
||||||
try {
|
try {
|
||||||
|
@ -357,6 +409,9 @@ export class OpenViduService {
|
||||||
return oldNickname !== this.participantService.getMyNickname();
|
return oldNickname !== this.participantService.getMyNickname();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isMyOwnConnection(connectionId: string): boolean {
|
isMyOwnConnection(connectionId: string): boolean {
|
||||||
return (
|
return (
|
||||||
this.webcamSession?.connection?.connectionId === connectionId || this.screenSession?.connection?.connectionId === connectionId
|
this.webcamSession?.connection?.connectionId === connectionId || this.screenSession?.connection?.connectionId === connectionId
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, BehaviorSubject } from 'rxjs';
|
import { Observable, BehaviorSubject } from 'rxjs';
|
||||||
import { Publisher } from 'openvidu-browser/lib/OpenVidu/Publisher';
|
import { Publisher } from 'openvidu-browser/lib/OpenVidu/Publisher';
|
||||||
import { UserModel } from '../../models/user.model';
|
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ParticipantServiceMock {
|
export class ParticipantServiceMock {
|
||||||
OVUsers: Observable<UserModel[]>;
|
OVUsers: Observable<ParticipantAbstractModel[]>;
|
||||||
screenShareState: Observable<boolean>;
|
screenShareState: Observable<boolean>;
|
||||||
webcamVideoActive: Observable<boolean>;
|
webcamVideoActive: Observable<boolean>;
|
||||||
private _OVUsers = <BehaviorSubject<UserModel[]>>new BehaviorSubject([]);
|
private _OVUsers = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]);
|
||||||
private _screenShareState = <BehaviorSubject<boolean>>new BehaviorSubject(false);
|
private _screenShareState = <BehaviorSubject<boolean>>new BehaviorSubject(false);
|
||||||
private _webcamVideoActive = <BehaviorSubject<boolean>>new BehaviorSubject(true);
|
private _webcamVideoActive = <BehaviorSubject<boolean>>new BehaviorSubject(true);
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,17 @@ import { LoggerService } from '../logger/logger.service';
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ParticipantService {
|
export class ParticipantService {
|
||||||
//Local participants observables
|
/**
|
||||||
|
* @internal
|
||||||
|
* Local participants observables
|
||||||
|
*/
|
||||||
localParticipantObs: Observable<ParticipantAbstractModel>;
|
localParticipantObs: Observable<ParticipantAbstractModel>;
|
||||||
protected _localParticipant = <BehaviorSubject<ParticipantAbstractModel>>new BehaviorSubject(null);
|
protected _localParticipant = <BehaviorSubject<ParticipantAbstractModel>>new BehaviorSubject(null);
|
||||||
|
|
||||||
//Remote participants observable
|
/**
|
||||||
|
* @internal
|
||||||
|
* Remote participants observables
|
||||||
|
*/
|
||||||
remoteParticipantsObs: Observable<ParticipantAbstractModel[]>;
|
remoteParticipantsObs: Observable<ParticipantAbstractModel[]>;
|
||||||
protected _remoteParticipants = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]);
|
protected _remoteParticipants = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]);
|
||||||
|
|
||||||
|
@ -24,6 +30,9 @@ export class ParticipantService {
|
||||||
|
|
||||||
protected log: ILogger;
|
protected log: ILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
constructor(protected openviduAngularConfigSrv: OpenViduAngularConfigService, protected loggerSrv: LoggerService) {
|
constructor(protected openviduAngularConfigSrv: OpenViduAngularConfigService, protected loggerSrv: LoggerService) {
|
||||||
this.log = this.loggerSrv.get('ParticipantService');
|
this.log = this.loggerSrv.get('ParticipantService');
|
||||||
|
|
||||||
|
@ -31,7 +40,10 @@ export class ParticipantService {
|
||||||
this.remoteParticipantsObs = this._remoteParticipants.asObservable();
|
this.remoteParticipantsObs = this._remoteParticipants.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
initLocalParticipant(props: ParticipantProperties) {
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
initLocalParticipant(props: ParticipantProperties) {
|
||||||
this.localParticipant = this.newParticipant(props);
|
this.localParticipant = this.newParticipant(props);
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
@ -40,13 +52,22 @@ export class ParticipantService {
|
||||||
return this.localParticipant;
|
return this.localParticipant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getMyCameraPublisher(): Publisher {
|
getMyCameraPublisher(): Publisher {
|
||||||
return <Publisher>this.localParticipant.getCameraConnection().streamManager;
|
return <Publisher>this.localParticipant.getCameraConnection().streamManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setMyCameraPublisher(publisher: Publisher) {
|
setMyCameraPublisher(publisher: Publisher) {
|
||||||
this.localParticipant.setCameraPublisher(publisher);
|
this.localParticipant.setCameraPublisher(publisher);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setMyCameraConnectionId(connectionId: string) {
|
setMyCameraConnectionId(connectionId: string) {
|
||||||
this.localParticipant.setCameraConnectionId(connectionId);
|
this.localParticipant.setCameraConnectionId(connectionId);
|
||||||
}
|
}
|
||||||
|
@ -58,26 +79,39 @@ export class ParticipantService {
|
||||||
return <Publisher>this.localParticipant.getScreenConnection()?.streamManager;
|
return <Publisher>this.localParticipant.getScreenConnection()?.streamManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setMyScreenPublisher(publisher: Publisher) {
|
setMyScreenPublisher(publisher: Publisher) {
|
||||||
this.localParticipant.setScreenPublisher(publisher);
|
this.localParticipant.setScreenPublisher(publisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setMyScreenConnectionId(connectionId: string) {
|
setMyScreenConnectionId(connectionId: string) {
|
||||||
this.localParticipant.setScreenConnectionId(connectionId);
|
this.localParticipant.setScreenConnectionId(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
enableWebcamStream() {
|
enableWebcamStream() {
|
||||||
this.localParticipant.enableCamera();
|
this.localParticipant.enableCamera();
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
disableWebcamStream() {
|
disableWebcamStream() {
|
||||||
this.localParticipant.disableCamera();
|
this.localParticipant.disableCamera();
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
activeMyScreenShare(screenPublisher: Publisher) {
|
activeMyScreenShare(screenPublisher: Publisher) {
|
||||||
this.log.d('Enabling screen publisher');
|
this.log.d('Enabling screen publisher');
|
||||||
|
|
||||||
|
@ -96,16 +130,24 @@ export class ParticipantService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
disableScreenStream() {
|
disableScreenStream() {
|
||||||
this.localParticipant.disableScreen();
|
this.localParticipant.disableScreen();
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setMyNickname(nickname: string) {
|
setMyNickname(nickname: string) {
|
||||||
this.localParticipant.setNickname(nickname);
|
this.localParticipant.setNickname(nickname);
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getMyNickname(): string {
|
getMyNickname(): string {
|
||||||
return this.localParticipant.nickname;
|
return this.localParticipant.nickname;
|
||||||
}
|
}
|
||||||
|
@ -113,13 +155,13 @@ export class ParticipantService {
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
toggleMyVideoEnlarged(connectionId: string) {
|
toggleMyVideoEnlarged(connectionId: string) {
|
||||||
this.localParticipant.toggleVideoEnlarged(connectionId);
|
this.localParticipant.toggleVideoEnlarged(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
resetMyStreamsToNormalSize() {
|
resetMyStreamsToNormalSize() {
|
||||||
if (this.localParticipant.someHasVideoEnlarged()) {
|
if (this.localParticipant.someHasVideoEnlarged()) {
|
||||||
this.localParticipant.setAllVideoEnlarged(false);
|
this.localParticipant.setAllVideoEnlarged(false);
|
||||||
|
@ -127,6 +169,9 @@ export class ParticipantService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
this.disableScreenStream();
|
this.disableScreenStream();
|
||||||
// this.localParticipant = this.newParticipant();
|
// this.localParticipant = this.newParticipant();
|
||||||
|
@ -137,34 +182,58 @@ export class ParticipantService {
|
||||||
this.updateLocalParticipant();
|
this.updateLocalParticipant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isMyCameraActive(): boolean {
|
isMyCameraActive(): boolean {
|
||||||
return this.localParticipant.isCameraActive();
|
return this.localParticipant.isCameraActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isMyScreenActive(): boolean {
|
isMyScreenActive(): boolean {
|
||||||
return this.localParticipant.isScreenActive();
|
return this.localParticipant.isScreenActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isOnlyMyCameraActive(): boolean {
|
isOnlyMyCameraActive(): boolean {
|
||||||
return this.isMyCameraActive() && !this.isMyScreenActive();
|
return this.isMyCameraActive() && !this.isMyScreenActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
isOnlyMyScreenActive(): boolean {
|
isOnlyMyScreenActive(): boolean {
|
||||||
return this.isMyScreenActive() && !this.isMyCameraActive();
|
return this.isMyScreenActive() && !this.isMyCameraActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
haveICameraAndScreenActive(): boolean {
|
haveICameraAndScreenActive(): boolean {
|
||||||
return this.isMyCameraActive() && this.isMyScreenActive();
|
return this.isMyCameraActive() && this.isMyScreenActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
hasCameraVideoActive(): boolean {
|
hasCameraVideoActive(): boolean {
|
||||||
return this.localParticipant.isCameraVideoActive();
|
return this.localParticipant.isCameraVideoActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
hasCameraAudioActive(): boolean {
|
hasCameraAudioActive(): boolean {
|
||||||
return this.localParticipant?.isCameraAudioActive();
|
return this.localParticipant?.isCameraAudioActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
hasScreenAudioActive(): boolean {
|
hasScreenAudioActive(): boolean {
|
||||||
return this.localParticipant.isScreenAudioActive();
|
return this.localParticipant.isScreenAudioActive();
|
||||||
}
|
}
|
||||||
|
@ -177,14 +246,16 @@ export class ParticipantService {
|
||||||
* REMOTE USERS
|
* REMOTE USERS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addRemoteConnection(connectionId:string, data: string, subscriber: Subscriber) {
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
addRemoteConnection(connectionId: string, data: string, subscriber: Subscriber) {
|
||||||
const type: VideoType = this.getTypeConnectionData(data);
|
const type: VideoType = this.getTypeConnectionData(data);
|
||||||
const streamModel: StreamModel = {
|
const streamModel: StreamModel = {
|
||||||
type,
|
type,
|
||||||
videoEnlarged: type === VideoType.SCREEN,
|
videoEnlarged: type === VideoType.SCREEN,
|
||||||
streamManager: subscriber,
|
streamManager: subscriber,
|
||||||
connected: true,
|
connected: true,
|
||||||
connectionId
|
connectionId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,12 +266,12 @@ export class ParticipantService {
|
||||||
const participantAdded = this.getRemoteParticipantById(participantId);
|
const participantAdded = this.getRemoteParticipantById(participantId);
|
||||||
if (!!participantAdded) {
|
if (!!participantAdded) {
|
||||||
this.log.d('Adding connection to existing participant: ', participantId);
|
this.log.d('Adding connection to existing participant: ', participantId);
|
||||||
if(participantAdded.hasConnectionType(streamModel.type)) {
|
if (participantAdded.hasConnectionType(streamModel.type)) {
|
||||||
this.log.d('Participant has publisher, updating it');
|
this.log.d('Participant has publisher, updating it');
|
||||||
participantAdded.setPublisher(streamModel.type, subscriber);
|
participantAdded.setPublisher(streamModel.type, subscriber);
|
||||||
} else {
|
} else {
|
||||||
this.log.d('Participant has not publisher, adding it');
|
this.log.d('Participant has not publisher, adding it');
|
||||||
if(streamModel.type === VideoType.SCREEN) {
|
if (streamModel.type === VideoType.SCREEN) {
|
||||||
this.resetRemoteStreamsToNormalSize();
|
this.resetRemoteStreamsToNormalSize();
|
||||||
this.resetMyStreamsToNormalSize();
|
this.resetMyStreamsToNormalSize();
|
||||||
}
|
}
|
||||||
|
@ -212,18 +283,28 @@ export class ParticipantService {
|
||||||
nickname: this.getNicknameFromConnectionData(data),
|
nickname: this.getNicknameFromConnectionData(data),
|
||||||
local: false,
|
local: false,
|
||||||
id: participantId
|
id: participantId
|
||||||
}
|
};
|
||||||
const remoteParticipant = this.newParticipant(props, streamModel);
|
const remoteParticipant = this.newParticipant(props, streamModel);
|
||||||
this.remoteParticipants.push(remoteParticipant);
|
this.remoteParticipants.push(remoteParticipant);
|
||||||
}
|
}
|
||||||
this.updateRemoteParticipants();
|
this.updateRemoteParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRemoteParticipants(): ParticipantAbstractModel[] {
|
||||||
|
return this.remoteParticipants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
resetRemoteStreamsToNormalSize() {
|
resetRemoteStreamsToNormalSize() {
|
||||||
this.remoteParticipants.forEach(participant => participant.setAllVideoEnlarged(false));
|
this.remoteParticipants.forEach((participant) => participant.setAllVideoEnlarged(false));
|
||||||
this.updateRemoteParticipants();
|
this.updateRemoteParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
removeConnectionByConnectionId(connectionId: string) {
|
removeConnectionByConnectionId(connectionId: string) {
|
||||||
this.log.w('Deleting connection: ', connectionId);
|
this.log.w('Deleting connection: ', connectionId);
|
||||||
let participant = null;
|
let participant = null;
|
||||||
|
@ -240,13 +321,13 @@ export class ParticipantService {
|
||||||
// Remove participants without connections
|
// Remove participants without connections
|
||||||
this.remoteParticipants = this.remoteParticipants.filter((p) => p !== participant);
|
this.remoteParticipants = this.remoteParticipants.filter((p) => p !== participant);
|
||||||
}
|
}
|
||||||
if(removeStream.type === VideoType.SCREEN){
|
if (removeStream.type === VideoType.SCREEN) {
|
||||||
const remoteScreens = this.remoteParticipants.filter(p => p.isScreenActive());
|
const remoteScreens = this.remoteParticipants.filter((p) => p.isScreenActive());
|
||||||
if(remoteScreens.length > 0){
|
if (remoteScreens.length > 0) {
|
||||||
// Enlarging the last screen connection active
|
// Enlarging the last screen connection active
|
||||||
const lastScreenActive = remoteScreens[remoteScreens.length -1];
|
const lastScreenActive = remoteScreens[remoteScreens.length - 1];
|
||||||
lastScreenActive.setScreenEnlarged(true);
|
lastScreenActive.setScreenEnlarged(true);
|
||||||
} else if(this.localParticipant.isScreenActive()) {
|
} else if (this.localParticipant.isScreenActive()) {
|
||||||
// Enlarging my screen if thereare not any remote screen active
|
// Enlarging my screen if thereare not any remote screen active
|
||||||
this.localParticipant.setScreenEnlarged(true);
|
this.localParticipant.setScreenEnlarged(true);
|
||||||
}
|
}
|
||||||
|
@ -255,6 +336,9 @@ export class ParticipantService {
|
||||||
this.updateRemoteParticipants();
|
this.updateRemoteParticipants();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getRemoteParticipantByConnectionId(connectionId: string): ParticipantAbstractModel {
|
getRemoteParticipantByConnectionId(connectionId: string): ParticipantAbstractModel {
|
||||||
return this.remoteParticipants.find((p) => p.hasConnectionId(connectionId));
|
return this.remoteParticipants.find((p) => p.hasConnectionId(connectionId));
|
||||||
}
|
}
|
||||||
|
@ -262,15 +346,24 @@ export class ParticipantService {
|
||||||
protected getRemoteParticipantById(id: string): ParticipantAbstractModel {
|
protected getRemoteParticipantById(id: string): ParticipantAbstractModel {
|
||||||
return this.remoteParticipants.find((p) => p.id === id);
|
return this.remoteParticipants.find((p) => p.id === id);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
someoneIsSharingScreen(): boolean {
|
someoneIsSharingScreen(): boolean {
|
||||||
return this.remoteParticipants.some((p) => p.someHasVideoEnlarged());
|
return this.remoteParticipants.some((p) => p.someHasVideoEnlarged());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
toggleRemoteVideoEnlarged(connectionId: string) {
|
toggleRemoteVideoEnlarged(connectionId: string) {
|
||||||
const p = this.getRemoteParticipantByConnectionId(connectionId);
|
const p = this.getRemoteParticipantByConnectionId(connectionId);
|
||||||
p.toggleVideoEnlarged(connectionId);
|
p.toggleVideoEnlarged(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
getNicknameFromConnectionData(data: string): string {
|
getNicknameFromConnectionData(data: string): string {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(data).clientData;
|
return JSON.parse(data).clientData;
|
||||||
|
@ -279,6 +372,9 @@ export class ParticipantService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
setRemoteNickname(connectionId: string, nickname: string) {
|
setRemoteNickname(connectionId: string, nickname: string) {
|
||||||
const participant = this.getRemoteParticipantByConnectionId(connectionId);
|
const participant = this.getRemoteParticipantByConnectionId(connectionId);
|
||||||
if (participant) {
|
if (participant) {
|
||||||
|
@ -308,8 +404,7 @@ export class ParticipantService {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected newParticipant(props: ParticipantProperties, streamModel?: StreamModel) {
|
protected newParticipant(props: ParticipantProperties, streamModel?: StreamModel) {
|
||||||
|
if (this.openviduAngularConfigSrv.hasParticipantFactory()) {
|
||||||
if(this.openviduAngularConfigSrv.hasParticipantFactory()){
|
|
||||||
return this.openviduAngularConfigSrv.getParticipantFactory().apply(this, [props, streamModel]);
|
return this.openviduAngularConfigSrv.getParticipantFactory().apply(this, [props, streamModel]);
|
||||||
}
|
}
|
||||||
return new ParticipantModel(props, streamModel);
|
return new ParticipantModel(props, streamModel);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,6 +4,9 @@ import { ILogger } from '../../models/logger.model';
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../models/menu.model';
|
||||||
import { LoggerService } from '../logger/logger.service';
|
import { LoggerService } from '../logger/logger.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { ILogger } from '../../models/logger.model';
|
||||||
import { LoggerService } from '../logger/logger.service';
|
import { LoggerService } from '../logger/logger.service';
|
||||||
import { Storage } from '../../models/storage.model';
|
import { Storage } from '../../models/storage.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<ov-videoconference
|
||||||
|
*ngIf="success"
|
||||||
|
[participantName]="_participantName"
|
||||||
|
[tokens]="_tokens"
|
||||||
|
[minimal]="_minimal"
|
||||||
|
[prejoin]="_prejoin"
|
||||||
|
[videoMuted]="_videoMuted"
|
||||||
|
[audioMuted]="_audioMuted"
|
||||||
|
[toolbarScreenshareButton]="_toolbarScreenshareButton"
|
||||||
|
[toolbarFullscreenButton]="_toolbarFullscreenButton"
|
||||||
|
[toolbarLeaveButton]="_toolbarLeaveButton"
|
||||||
|
[toolbarChatPanelButton]="_toolbarChatPanelButton"
|
||||||
|
[toolbarParticipantsPanelButton]="_toolbarParticipantsPanelButton"
|
||||||
|
[toolbarDisplayLogo]="_toolbarDisplayLogo"
|
||||||
|
[toolbarDisplaySessionName]="_toolbarDisplaySessionName"
|
||||||
|
[streamDisplayParticipantName]="_streamDisplayParticipantName"
|
||||||
|
[streamDisplayAudioDetection]="_streamDisplayAudioDetection"
|
||||||
|
[streamSettingsButton]="_streamSettingsButton"
|
||||||
|
[participantPanelItemMuteButton]="_participantPanelItemMuteButton"
|
||||||
|
(onJoinButtonClicked)="_onJoinButtonClicked()"
|
||||||
|
(onToolbarLeaveButtonClicked)="_onToolbarLeaveButtonClicked()"
|
||||||
|
(onToolbarCameraButtonClicked)="_onToolbarCameraButtonClicked()"
|
||||||
|
(onToolbarMicrophoneButtonClicked)="_onToolbarMicrophoneButtonClicked()"
|
||||||
|
(onToolbarScreenshareButtonClicked)="_onToolbarScreenshareButtonClicked()"
|
||||||
|
(onToolbarParticipantsPanelButtonClicked)="_onToolbarParticipantsPanelButtonClicked()"
|
||||||
|
(onToolbarChatPanelButtonClicked)="_onToolbarChatPanelButtonClicked()"
|
||||||
|
(onToolbarFullscreenButtonClicked)="_onToolbarFullscreenButtonClicked()"
|
||||||
|
(onSessionCreated)="_onSessionCreated($event)"
|
||||||
|
(onParticipantCreated)="_onParticipantCreated($event)"
|
||||||
|
></ov-videoconference>
|
|
@ -8,57 +8,81 @@ export interface TokenModel {
|
||||||
screen: string;
|
screen: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* **OpenviduWebComponentComponent** is a wrapped of the {@link VideoconferenceComponent} which allows to generate and export the OpenVidu Webcomponent
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
templateUrl: './openvidu-webcomponent.component.html'
|
||||||
<ov-videoconference
|
|
||||||
*ngIf="success"
|
|
||||||
[participantName]="_participantName"
|
|
||||||
[tokens]="_tokens"
|
|
||||||
[minimal]="_minimal"
|
|
||||||
[prejoin]="_prejoin"
|
|
||||||
[videoMuted]="_videoMuted"
|
|
||||||
[audioMuted]="_audioMuted"
|
|
||||||
[toolbarScreenshareButton]="_toolbarScreenshareButton"
|
|
||||||
[toolbarFullscreenButton]="_toolbarFullscreenButton"
|
|
||||||
[toolbarLeaveButton]="_toolbarLeaveButton"
|
|
||||||
[toolbarChatPanelButton]="_toolbarChatPanelButton"
|
|
||||||
[toolbarParticipantsPanelButton]="_toolbarParticipantsPanelButton"
|
|
||||||
[toolbarDisplayLogo]="_toolbarDisplayLogo"
|
|
||||||
[toolbarDisplaySessionName]="_toolbarDisplaySessionName"
|
|
||||||
[streamDisplayParticipantName]="_streamDisplayParticipantName"
|
|
||||||
[streamDisplayAudioDetection]="_streamDisplayAudioDetection"
|
|
||||||
[streamSettingsButton]="_streamSettingsButton"
|
|
||||||
[participantPanelItemMuteButton]="_participantPanelItemMuteButton"
|
|
||||||
(onJoinButtonClicked)="_onJoinButtonClicked()"
|
|
||||||
(onToolbarLeaveButtonClicked)="_onToolbarLeaveButtonClicked()"
|
|
||||||
(onToolbarCameraButtonClicked)="_onToolbarCameraButtonClicked()"
|
|
||||||
(onToolbarMicrophoneButtonClicked)="_onToolbarMicrophoneButtonClicked()"
|
|
||||||
(onToolbarScreenshareButtonClicked)="_onToolbarScreenshareButtonClicked()"
|
|
||||||
(onToolbarParticipantsPanelButtonClicked)="_onToolbarParticipantsPanelButtonClicked()"
|
|
||||||
(onToolbarChatPanelButtonClicked)="_onToolbarChatPanelButtonClicked()"
|
|
||||||
(onToolbarFullscreenButtonClicked)="_onToolbarFullscreenButtonClicked()"
|
|
||||||
(onSessionCreated)="_onSessionCreated($event)"
|
|
||||||
(onParticipantCreated)="_onParticipantCreated($event)"
|
|
||||||
></ov-videoconference>
|
|
||||||
`
|
|
||||||
})
|
})
|
||||||
export class OpenviduWebComponentComponent implements OnInit {
|
export class OpenviduWebComponentComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_tokens: TokenModel;
|
_tokens: TokenModel;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_minimal: boolean = false;
|
_minimal: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_participantName: string;
|
_participantName: string;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_prejoin: boolean = true;
|
_prejoin: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_videoMuted: boolean = false;
|
_videoMuted: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_audioMuted: boolean = false;
|
_audioMuted: boolean = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarScreenshareButton: boolean = true;
|
_toolbarScreenshareButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarFullscreenButton: boolean = true;
|
_toolbarFullscreenButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarLeaveButton: boolean = true;
|
_toolbarLeaveButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarChatPanelButton: boolean = true;
|
_toolbarChatPanelButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarParticipantsPanelButton: boolean = true;
|
_toolbarParticipantsPanelButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarDisplayLogo: boolean = true;
|
_toolbarDisplayLogo: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_toolbarDisplaySessionName: boolean = true;
|
_toolbarDisplaySessionName: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_streamDisplayParticipantName: boolean = true;
|
_streamDisplayParticipantName: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_streamDisplayAudioDetection: boolean = true;
|
_streamDisplayAudioDetection: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_streamSettingsButton: boolean = true;
|
_streamSettingsButton: boolean = true;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_participantPanelItemMuteButton: boolean = true;
|
_participantPanelItemMuteButton: boolean = true;
|
||||||
|
|
||||||
@Input() set minimal(value: string | boolean) {
|
@Input() set minimal(value: string | boolean) {
|
||||||
|
@ -122,9 +146,15 @@ export class OpenviduWebComponentComponent implements OnInit {
|
||||||
@Output() onSessionCreated = new EventEmitter<any>();
|
@Output() onSessionCreated = new EventEmitter<any>();
|
||||||
@Output() onParticipantCreated = new EventEmitter<any>();
|
@Output() onParticipantCreated = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
success: boolean = false;
|
success: boolean = false;
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
constructor(private loggerService: LoggerService, private host: ElementRef, private openviduService: OpenViduService) {
|
constructor(private loggerService: LoggerService, private host: ElementRef, private openviduService: OpenViduService) {
|
||||||
this.log = this.loggerService.get('WebComponent');
|
this.log = this.loggerService.get('WebComponent');
|
||||||
this.host.nativeElement.leaveSession = this.leaveSession.bind(this);
|
this.host.nativeElement.leaveSession = this.leaveSession.bind(this);
|
||||||
|
@ -147,37 +177,68 @@ export class OpenviduWebComponentComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onJoinButtonClicked() {
|
_onJoinButtonClicked() {
|
||||||
this.onJoinButtonClicked.emit();
|
this.onJoinButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarLeaveButtonClicked() {
|
_onToolbarLeaveButtonClicked() {
|
||||||
|
this.success = false;
|
||||||
this.onToolbarLeaveButtonClicked.emit();
|
this.onToolbarLeaveButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarCameraButtonClicked() {
|
_onToolbarCameraButtonClicked() {
|
||||||
this.onToolbarCameraButtonClicked.emit();
|
this.onToolbarCameraButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarMicrophoneButtonClicked() {
|
_onToolbarMicrophoneButtonClicked() {
|
||||||
this.onToolbarMicrophoneButtonClicked.emit();
|
this.onToolbarMicrophoneButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarScreenshareButtonClicked() {
|
_onToolbarScreenshareButtonClicked() {
|
||||||
this.onToolbarScreenshareButtonClicked.emit();
|
this.onToolbarScreenshareButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarParticipantsPanelButtonClicked() {
|
_onToolbarParticipantsPanelButtonClicked() {
|
||||||
this.onToolbarParticipantsPanelButtonClicked.emit();
|
this.onToolbarParticipantsPanelButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarChatPanelButtonClicked() {
|
_onToolbarChatPanelButtonClicked() {
|
||||||
this.onToolbarChatPanelButtonClicked.emit();
|
this.onToolbarChatPanelButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onToolbarFullscreenButtonClicked() {
|
_onToolbarFullscreenButtonClicked() {
|
||||||
this.onToolbarFullscreenButtonClicked.emit();
|
this.onToolbarFullscreenButtonClicked.emit();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onSessionCreated(event: Session) {
|
_onSessionCreated(event: Session) {
|
||||||
this.onSessionCreated.emit(event);
|
this.onSessionCreated.emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
_onParticipantCreated(event: ParticipantAbstractModel) {
|
_onParticipantCreated(event: ParticipantAbstractModel) {
|
||||||
this.onParticipantCreated.emit(event);
|
this.onParticipantCreated.emit(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "OpenVidu Angular Documentation",
|
||||||
|
"output": "docs/openvidu-angular",
|
||||||
|
"hideGenerator": true,
|
||||||
|
"disableLifeCycleHooks": true,
|
||||||
|
"disableProtected": true,
|
||||||
|
"disableInternal": true,
|
||||||
|
"disablePrivate": true,
|
||||||
|
"disableCoverage": true,
|
||||||
|
"disableRoutesGraph": true,
|
||||||
|
"disableSourceCode": true,
|
||||||
|
"disableTemplateTab": true,
|
||||||
|
"disableDomTree": true,
|
||||||
|
"disableStyleTab": true,
|
||||||
|
"disableDependencies": true,
|
||||||
|
"theme": "gitbook",
|
||||||
|
"customFavicon": "src/favicon.ico",
|
||||||
|
"extTheme": "src/doc/"
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
@import "./reset.css";
|
||||||
|
@import "./bootstrap.min.css";
|
||||||
|
@import "./bootstrap-card.css";
|
||||||
|
@import "./prism.css";
|
||||||
|
@import "./ionicons.min.css";
|
||||||
|
@import "./compodoc.css";
|
||||||
|
@import "./tablesort.css";
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
/* .getting-started {
|
||||||
|
display: none;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.token.property, .token.tag, .token.constant, .token.symbol, .token.deleted {
|
||||||
|
color: rgb(0, 204, 255);
|
||||||
|
|
||||||
|
}
|
||||||
|
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted {
|
||||||
|
color: #d3ff7c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule, .token.attr-value, .token.function, .token.class-name {
|
||||||
|
color: rgb(255, 170, 72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.component-link-text {
|
||||||
|
padding-top: 5px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
div>p {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
|
||||||
|
background-color: rgb(233, 245, 255);
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.directive section, .module-graph-container, .card-module>.card-block>p,
|
||||||
|
nav a[href*="license.html"],
|
||||||
|
nav a[href*="properties.html"],
|
||||||
|
nav a[href*="overview.html"],
|
||||||
|
nav a[href*="index.html"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-module {
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table-container table {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table-container>div {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warn-container, .info-container {
|
||||||
|
display: table;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
padding: 5px 0 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-container > span, .warn-container >span {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warn-container {
|
||||||
|
border: 2px solid #ffb600;
|
||||||
|
background-color: #FFFBF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-container {
|
||||||
|
border: 2px solid #0077ff;
|
||||||
|
background-color: #f1feff;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"include": [
|
||||||
|
"../../projects/openvidu-angular/src/lib/components/**/*.ts",
|
||||||
|
"../../projects/openvidu-angular/src/lib/directives/**/*.ts",
|
||||||
|
"../../projects/openvidu-angular/src/lib/services/**/*.ts",
|
||||||
|
"../../projects/openvidu-angular/src/lib/models/**/*.ts",
|
||||||
|
"../app/openvidu-webcomponent/openvidu-webcomponent.component.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"../../projects/openvidu-angular/src/lib/**/*.mock.ts",
|
||||||
|
"../../projects/openvidu-angular/src/lib/**/*.spec.ts"
|
||||||
|
],
|
||||||
|
}
|
Loading…
Reference in New Issue