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: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: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:serve-testapp": "npx http-server ./e2e/webcomponent-app/",
|
||||
"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-cli": "13.0.0",
|
||||
"@angular/elements": "13.0.0",
|
||||
"@compodoc/compodoc": "^1.1.19",
|
||||
"@types/chai": "4.3.0",
|
||||
"@types/mocha": "9.1.0",
|
||||
"@types/node": "16.11.6",
|
||||
|
|
|
@ -2,6 +2,10 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
|||
|
||||
import { PublisherSpeakingEvent, StreamManager } from 'openvidu-browser';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@Component({
|
||||
selector: 'ov-audio-wave',
|
||||
templateUrl: './audio-wave.component.html',
|
||||
|
@ -9,7 +13,7 @@ import { PublisherSpeakingEvent, StreamManager } from 'openvidu-browser';
|
|||
})
|
||||
export class AudioWaveComponent implements OnInit, OnDestroy {
|
||||
isSpeaking: boolean = false;
|
||||
audioVolume: number = 0;
|
||||
// audioVolume: number = 0;
|
||||
|
||||
private _streamManager: StreamManager;
|
||||
|
||||
|
@ -17,7 +21,7 @@ export class AudioWaveComponent implements OnInit, OnDestroy {
|
|||
set streamManager(streamManager: StreamManager) {
|
||||
this._streamManager = streamManager;
|
||||
|
||||
if(this._streamManager) {
|
||||
if (this._streamManager) {
|
||||
this._streamManager.on('publisherStartSpeaking', (event: PublisherSpeakingEvent) => {
|
||||
this.isSpeaking = true;
|
||||
});
|
||||
|
@ -34,12 +38,11 @@ export class AudioWaveComponent implements OnInit, OnDestroy {
|
|||
// console.log('AUDIO VOLUME', this.audioVolume);
|
||||
// });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
constructor() {}
|
||||
ngOnDestroy(): void {
|
||||
if(this._streamManager){
|
||||
if (this._streamManager) {
|
||||
this._streamManager.off('publisherStartSpeaking');
|
||||
this._streamManager.off('publisherStopSpeaking');
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@Component({
|
||||
selector: 'ov-avatar-profile',
|
||||
template: `
|
||||
|
|
|
@ -13,8 +13,40 @@ import { ParticipantService } from '../../services/participant/participant.servi
|
|||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
import { LayoutService } from '../../services/layout/layout.service';
|
||||
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({
|
||||
selector: 'ov-layout',
|
||||
templateUrl: './layout.component.html',
|
||||
|
@ -22,8 +54,14 @@ import { OpenViduAngularConfigService } from '../../services/config/openvidu-ang
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild(StreamDirective)
|
||||
set externalStream(externalStream: StreamDirective) {
|
||||
// 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 remoteParticipantsSubs: Subscription;
|
||||
|
||||
constructor(
|
||||
protected layoutService: LayoutService,
|
||||
protected participantService: ParticipantService,
|
||||
private libService: OpenViduAngularConfigService,
|
||||
private cd: ChangeDetectorRef
|
||||
) {}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(protected layoutService: LayoutService, protected participantService: ParticipantService, private cd: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.subscribeToParticipants();
|
||||
|
@ -51,10 +87,6 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
|
||||
ngAfterViewInit() {
|
||||
let timeout: number = 0;
|
||||
// if (this.libService.isWebcomponent()) {
|
||||
// timeout = 0;
|
||||
// }
|
||||
|
||||
this.layoutService.initialize(timeout);
|
||||
this.layoutService.update(timeout);
|
||||
}
|
||||
|
@ -67,7 +99,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
this.layoutService.clear();
|
||||
}
|
||||
|
||||
protected subscribeToParticipants() {
|
||||
private subscribeToParticipants() {
|
||||
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
|
||||
this.localParticipant = p;
|
||||
this.layoutService.update();
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface DialogData {
|
||||
title: string;
|
||||
description: string;
|
||||
showActionButtons: boolean;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@Component({
|
||||
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 { ChatMessage } from '../../../models/chat.model';
|
||||
import { MenuType } from '../../../models/menu.model';
|
||||
import { ChatService } from '../../../services/chat/chat.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({
|
||||
selector: 'ov-chat-panel',
|
||||
templateUrl: './chat-panel.component.html',
|
||||
|
@ -12,16 +45,31 @@ import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ChatPanelComponent implements OnInit, AfterViewInit {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild('chatScroll') chatScroll: ElementRef;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild('chatInput') chatInput: ElementRef;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
message: string;
|
||||
|
||||
messageList: ChatMessage[] = [];
|
||||
isMenuOpened: boolean;
|
||||
|
||||
private chatMessageSubscription: Subscription;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(private chatService: ChatService, private menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@HostListener('document:keydown.escape', ['$event'])
|
||||
onKeydownHandler(event: KeyboardEvent) {
|
||||
if (this.menuService.isMenuOpened()) {
|
||||
|
@ -44,6 +92,9 @@ export class ChatPanelComponent implements OnInit, AfterViewInit {
|
|||
if (this.chatMessageSubscription) this.chatMessageSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
eventKeyPress(event) {
|
||||
// Pressed 'Enter' key
|
||||
if (event && event.keyCode === 13) {
|
||||
|
@ -53,7 +104,7 @@ export class ChatPanelComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
|
||||
sendMessage(): void {
|
||||
if(!!this.message) {
|
||||
if (!!this.message) {
|
||||
this.chatService.sendMessage(this.message);
|
||||
this.message = '';
|
||||
}
|
||||
|
|
|
@ -4,6 +4,42 @@ import { ChatPanelDirective, ParticipantsPanelDirective } from '../../directives
|
|||
import { MenuType } from '../../models/menu.model';
|
||||
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({
|
||||
selector: 'ov-panel',
|
||||
templateUrl: './panel.component.html',
|
||||
|
@ -11,7 +47,14 @@ import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.ser
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class PanelComponent implements OnInit {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('participantsPanel', { read: TemplateRef }) participantsPanelTemplate: TemplateRef<any>;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('chatPanel', { read: TemplateRef }) chatPanelTemplate: TemplateRef<any>;
|
||||
|
||||
@ContentChild(ParticipantsPanelDirective)
|
||||
|
@ -34,23 +77,28 @@ export class PanelComponent implements OnInit {
|
|||
|
||||
isParticipantsPanelOpened: boolean;
|
||||
isChatPanelOpened: boolean;
|
||||
menuSubscription: Subscription;
|
||||
private menuSubscription: Subscription;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(protected menuService: SidenavMenuService, private cd: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
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() {
|
||||
this.isChatPanelOpened = false;
|
||||
this.isParticipantsPanelOpened = false;
|
||||
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 { 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({
|
||||
selector: 'ov-participant-panel-item',
|
||||
templateUrl: './participant-panel-item.component.html',
|
||||
|
@ -11,10 +59,20 @@ import { OpenViduAngularConfigService } from '../../../../services/config/openvi
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('participantPanelItemElements', { read: TemplateRef }) participantPanelItemElementsTemplate: TemplateRef<any>;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showMuteButton: boolean = true;
|
||||
private muteButtonSub: Subscription;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild(ParticipantPanelItemElementsDirective)
|
||||
set externalItemElements(externalItemElements: ParticipantPanelItemElementsDirective) {
|
||||
// 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()
|
||||
set participant(p: ParticipantAbstractModel) {
|
||||
this._participant = p;
|
||||
set participant(participant: ParticipantAbstractModel) {
|
||||
this._participant = participant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
_participant: ParticipantAbstractModel;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(private libService: OpenViduAngularConfigService, private cd: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -39,6 +104,9 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
|
|||
if (this.muteButtonSub) this.muteButtonSub.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleMuteForcibly() {
|
||||
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 { 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({
|
||||
selector: 'ov-participants-panel',
|
||||
templateUrl: './participants-panel.component.html',
|
||||
|
@ -15,8 +48,9 @@ export class ParticipantsPanelComponent implements OnInit, OnDestroy {
|
|||
localParticipant: any;
|
||||
remoteParticipants: ParticipantAbstractModel[] = [];
|
||||
|
||||
private localParticipantSubs: Subscription;
|
||||
private remoteParticipantsSubs: Subscription;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('participantPanelItem', { read: TemplateRef }) participantPanelItemTemplate: TemplateRef<any>;
|
||||
|
||||
@ContentChild(ParticipantPanelItemDirective)
|
||||
|
@ -28,16 +62,19 @@ export class ParticipantsPanelComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
private localParticipantSubs: Subscription;
|
||||
private remoteParticipantsSubs: Subscription;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(
|
||||
protected participantService: ParticipantService,
|
||||
protected menuService: SidenavMenuService,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
|
||||
}
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p: ParticipantAbstractModel) => {
|
||||
this.localParticipant = p;
|
||||
// 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 { StorageService } from '../../services/storage/storage.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-pre-join',
|
||||
templateUrl: './pre-join.component.html',
|
||||
|
|
|
@ -27,6 +27,11 @@ import { LayoutService } from '../../services/layout/layout.service';
|
|||
import { Subscription, skip } from 'rxjs';
|
||||
import { MenuType } from '../../models/menu.model';
|
||||
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
||||
import { PlatformService } from '../../services/platform/platform.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@Component({
|
||||
selector: 'ov-session',
|
||||
|
@ -68,7 +73,8 @@ export class SessionComponent implements OnInit {
|
|||
protected chatService: ChatService,
|
||||
protected tokenService: TokenService,
|
||||
protected layoutService: LayoutService,
|
||||
protected menuService: SidenavMenuService
|
||||
protected menuService: SidenavMenuService,
|
||||
private platformService: PlatformService
|
||||
) {
|
||||
this.log = this.loggerSrv.get('SessionComponent');
|
||||
}
|
||||
|
@ -107,9 +113,9 @@ export class SessionComponent implements OnInit {
|
|||
|
||||
await this.connectToSession();
|
||||
// Workaround, firefox does not have audio when publisher join with muted camera
|
||||
// if (this.platformService.isFirefox() && !this.localUserService.hasCameraVideoActive()) {
|
||||
// this.openviduService.publishVideo(this.localUserService.getMyCameraPublisher(), true);
|
||||
// this.openviduService.publishVideo(this.localUserService.getMyCameraPublisher(), false);
|
||||
// if (this.platformService.isFirefox() && !this.participantService.hasCameraVideoActive()) {
|
||||
// this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);
|
||||
// this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), false);
|
||||
// }
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
<span *ngIf="videoSizeIcon === videoSizeIconEnum.NORMAL">Zoom out</span>
|
||||
<span *ngIf="videoSizeIcon === videoSizeIconEnum.BIG">Zoom in</span>
|
||||
</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>
|
||||
<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 { 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({
|
||||
selector: 'ov-stream',
|
||||
templateUrl: './stream.component.html',
|
||||
styleUrls: ['./stream.component.css']
|
||||
})
|
||||
export class StreamComponent implements OnInit {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild(MatMenuTrigger) public menuTrigger: MatMenuTrigger;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild('menu') menu: MatMenuPanel;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
videoSizeIconEnum = VideoSizeIcon;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
videoTypeEnum = VideoType;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
videoSizeIcon: VideoSizeIcon = VideoSizeIcon.BIG;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleNickname: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
_stream: StreamModel;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
nickname: string;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isMinimal: boolean = false;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showNickname: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showAudioDetection: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showSettingsButton: boolean = true;
|
||||
|
||||
private _streamContainer: ElementRef;
|
||||
|
||||
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
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild('streamContainer', { static: false, read: ElementRef })
|
||||
set streamContainer(streamContainer: ElementRef) {
|
||||
setTimeout(() => {
|
||||
|
@ -73,6 +134,9 @@ export class StreamComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ViewChild('nicknameInput')
|
||||
set nicknameInputElement(element: ElementRef) {
|
||||
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() {
|
||||
this.subscribeToStreamDirectives();
|
||||
}
|
||||
|
@ -89,8 +172,12 @@ export class StreamComponent implements OnInit {
|
|||
if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe();
|
||||
if (this.displayAudioDetectionSub) this.displayAudioDetectionSub.unsubscribe();
|
||||
if (this.displayParticipantNameSub) this.displayParticipantNameSub.unsubscribe();
|
||||
if (this.minimalSub) this.minimalSub.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleVideoEnlarged() {
|
||||
if (!!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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleVideoMenu(event) {
|
||||
if (this.menuTrigger.menuOpen) {
|
||||
this.menuTrigger.closeMenu();
|
||||
|
@ -111,16 +201,25 @@ export class StreamComponent implements OnInit {
|
|||
this.menuTrigger.openMenu();
|
||||
}
|
||||
|
||||
toggleSound() {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleMuteForcibly() {
|
||||
this._stream.participant.setMutedForcibly(!this._stream.participant.isMutedForcibly);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleNicknameForm() {
|
||||
if (this._stream.participant.local) {
|
||||
this.toggleNickname = !this.toggleNickname;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
updateNickname(event) {
|
||||
if (event?.keyCode === 13 || event?.type === 'focusout') {
|
||||
if (!!this.nickname) {
|
||||
|
@ -132,6 +231,9 @@ export class StreamComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
async replaceScreenTrack() {
|
||||
const properties: PublisherProperties = {
|
||||
videoSource: ScreenType.SCREEN,
|
||||
|
@ -147,7 +249,6 @@ export class StreamComponent implements OnInit {
|
|||
}
|
||||
|
||||
private subscribeToStreamDirectives() {
|
||||
|
||||
this.minimalSub = this.libService.minimalObs.subscribe((value: boolean) => {
|
||||
this.isMinimal = value;
|
||||
});
|
||||
|
|
|
@ -29,6 +29,60 @@ import { MenuType } from '../../models/menu.model';
|
|||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
|
||||
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({
|
||||
selector: 'ov-toolbar',
|
||||
templateUrl: './toolbar.component.html',
|
||||
|
@ -36,8 +90,14 @@ import { ToolbarAdditionalButtonsDirective } from '../../directives/template/ope
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ToolbarComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild('toolbarAdditionalButtons', { read: TemplateRef }) toolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@ContentChild(ToolbarAdditionalButtonsDirective)
|
||||
set externalAdditionalButtons(externalAdditionalButtons: ToolbarAdditionalButtonsDirective) {
|
||||
// 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() onChatPanelButtonClicked = new EventEmitter<any>();
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
session: Session;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
unreadMessages: number = 0;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
messageList: ChatMessage[] = [];
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isScreenShareActive: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isWebcamVideoActive: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isWebcamAudioActive: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isConnectionLost: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
hasVideoDevices: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
hasAudioDevices: boolean;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isFullscreenActive: boolean = false;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isChatOpened: boolean = false;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isParticipantsOpened: boolean = false;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isMinimal: boolean = false;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showScreenshareButton = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showFullscreenButton: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showLeaveButton: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showParticipantsPanelButton: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showChatPanelButton: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showLogo: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
showSessionName: boolean = true;
|
||||
|
||||
private log: ILogger;
|
||||
|
@ -91,25 +211,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
private displaySessionNameSub: Subscription;
|
||||
private currentWindowHeight = window.innerHeight;
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
keyDown(event: KeyboardEvent) {
|
||||
if (event.key === 'F11') {
|
||||
event.preventDefault();
|
||||
this.toggleFullscreen();
|
||||
this.currentWindowHeight = window.innerHeight;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(
|
||||
protected documentService: DocumentService,
|
||||
protected chatService: ChatService,
|
||||
|
@ -125,6 +229,30 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
) {
|
||||
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() {
|
||||
this.subscribeToToolbarDirectives();
|
||||
|
@ -151,8 +279,12 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
if (this.chatPanelButtonSub) this.chatPanelButtonSub.unsubscribe();
|
||||
if (this.displayLogoSub) this.displayLogoSub.unsubscribe();
|
||||
if (this.displaySessionNameSub) this.displaySessionNameSub.unsubscribe();
|
||||
if (this.minimalSub) this.minimalSub.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleMicrophone() {
|
||||
this.onMicrophoneButtonClicked.emit();
|
||||
|
||||
|
@ -166,6 +298,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
async toggleCamera() {
|
||||
this.onCameraButtonClicked.emit();
|
||||
|
||||
|
@ -200,6 +335,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
async toggleScreenShare() {
|
||||
this.onScreenshareButtonClicked.emit();
|
||||
|
||||
|
@ -277,22 +415,34 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
leaveSession() {
|
||||
this.log.d('Leaving session...');
|
||||
this.openviduService.disconnect();
|
||||
this.onLeaveButtonClicked.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleParticipantsPanel() {
|
||||
this.onParticipantsPanelButtonClicked.emit();
|
||||
this.menuService.toggleMenu(MenuType.PARTICIPANTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleChatPanel() {
|
||||
this.onChatPanelButtonClicked.emit();
|
||||
this.menuService.toggleMenu(MenuType.CHAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
toggleFullscreen() {
|
||||
this.isFullscreenActive = !this.isFullscreenActive;
|
||||
this.documentService.toggleFullscreen('session-container');
|
||||
|
|
|
@ -19,6 +19,9 @@ import { ActionService } from '../../services/action/action.service';
|
|||
import { ParticipantService } from '../../services/participant/participant.service';
|
||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-user-settings',
|
||||
templateUrl: './user-settings.component.html',
|
||||
|
|
|
@ -2,6 +2,9 @@ import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular
|
|||
import { StreamManager } from 'openvidu-browser';
|
||||
import { VideoType } from '../../models/video-type.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-video',
|
||||
template: `
|
||||
|
|
|
@ -48,12 +48,10 @@
|
|||
(onParticipantsPanelButtonClicked)="onParticipantsPanelButtonClicked()"
|
||||
(onChatPanelButtonClicked)="onChatPanelButtonClicked()"
|
||||
>
|
||||
|
||||
<ng-template #toolbarAdditionalButtons>
|
||||
<ng-container *ngTemplateOutlet="openviduAngularToolbarAdditionalButtonsTemplate"></ng-container>
|
||||
</ng-template>
|
||||
|
||||
</ov-toolbar>
|
||||
<ng-template #toolbarAdditionalButtons>
|
||||
<ng-container *ngTemplateOutlet="openviduAngularToolbarAdditionalButtonsTemplate"></ng-container>
|
||||
</ng-template>
|
||||
</ov-toolbar>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #defaultPanel>
|
||||
|
@ -84,11 +82,11 @@
|
|||
|
||||
<ng-template #defaultParticipantPanelItem let-participant>
|
||||
<ov-participant-panel-item [participant]="participant" id="default-participant-panel-item">
|
||||
|
||||
<ng-template #participantPanelItemElements>
|
||||
<ng-container *ngTemplateOutlet="openviduAngularParticipantPanelItemElementsTemplate; context: { $implicit: participant }"></ng-container>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="openviduAngularParticipantPanelItemElementsTemplate; context: { $implicit: participant }"
|
||||
></ng-container>
|
||||
</ng-template>
|
||||
|
||||
</ov-participant-panel-item>
|
||||
</ng-template>
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
} from '../../directives/template/openvidu-angular.directive';
|
||||
import { ILogger } from '../../models/logger.model';
|
||||
import { ParticipantProperties } from '../../models/participant.model';
|
||||
import { TokenModel } from '../../models/token.model';
|
||||
import { ActionService } from '../../services/action/action.service';
|
||||
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.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 { 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({
|
||||
selector: 'ov-videoconference',
|
||||
templateUrl: './videoconference.component.html',
|
||||
|
@ -41,40 +104,124 @@ import { TokenService } from '../../services/token/token.service';
|
|||
})
|
||||
export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
// *** Toolbar ***
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ToolbarDirective) externalToolbar: ToolbarDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ToolbarAdditionalButtonsDirective) externalToolbarAdditionalButtons: ToolbarAdditionalButtonsDirective;
|
||||
|
||||
// *** Panels ***
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(PanelDirective) externalPanel: PanelDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ChatPanelDirective) externalChatPanel: ChatPanelDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ParticipantsPanelDirective) externalParticipantsPanel: ParticipantsPanelDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ParticipantPanelItemDirective) externalParticipantPanelItem: ParticipantPanelItemDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(ParticipantPanelItemElementsDirective) externalParticipantPanelItemElements: ParticipantPanelItemElementsDirective;
|
||||
|
||||
// *** Layout ***
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(LayoutDirective) externalLayout: LayoutDirective;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ContentChild(StreamDirective) externalStream: StreamDirective;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultToolbar', { static: false, read: TemplateRef }) defaultToolbarTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultPanel', { static: false, read: TemplateRef }) defaultPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultChatPanel', { static: false, read: TemplateRef }) defaultChatPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultParticipantsPanel', { static: false, read: TemplateRef }) defaultParticipantsPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultParticipantPanelItem', { static: false, read: TemplateRef }) defaultParticipantPanelItemTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultLayout', { static: false, read: TemplateRef }) defaultLayoutTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ViewChild('defaultStream', { static: false, read: TemplateRef }) defaultStreamTemplate: TemplateRef<any>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularToolbarTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularToolbarAdditionalButtonsTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularChatPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularParticipantsPanelTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularParticipantPanelItemTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularParticipantPanelItemElementsTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
openviduAngularLayoutTemplate: TemplateRef<any>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
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()
|
||||
set tokens(tokens: { webcam: string; screen: string }) {
|
||||
set tokens(tokens: TokenModel) {
|
||||
if (!tokens || (!tokens.webcam && !tokens.screen)) {
|
||||
//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
|
||||
@Output() onParticipantCreated = new EventEmitter<any>();
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
joinSessionClicked: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
participantReady: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
canPublish: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
error: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
errorMessage: string = '';
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
showPrejoin: boolean = true;
|
||||
private externalParticipantName: string;
|
||||
private prejoinSub: Subscription;
|
||||
private participantNameSub: Subscription;
|
||||
private log: ILogger;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
constructor(
|
||||
private loggerSrv: LoggerService,
|
||||
private storageSrv: StorageService,
|
||||
|
@ -174,6 +341,9 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
|||
if (this.participantNameSub) this.participantNameSub.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
if (this.externalToolbar) {
|
||||
this.openviduAngularToolbarTemplate = this.externalToolbar.template;
|
||||
|
@ -239,34 +409,60 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onJoinButtonClicked() {
|
||||
this.joinSessionClicked = true;
|
||||
this.onJoinButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onLeaveButtonClicked() {
|
||||
this.joinSessionClicked = false;
|
||||
this.participantReady = false;
|
||||
this.onToolbarLeaveButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onCameraButtonClicked() {
|
||||
this.onToolbarCameraButtonClicked.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onMicrophoneButtonClicked() {
|
||||
this.onToolbarMicrophoneButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onScreenshareButtonClicked() {
|
||||
this.onToolbarScreenshareButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onFullscreenButtonClicked() {
|
||||
this.onToolbarFullscreenButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onParticipantsPanelButtonClicked() {
|
||||
this.onToolbarParticipantsPanelButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onChatPanelButtonClicked() {
|
||||
this.onToolbarChatPanelButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onSessionCreated(event: Session) {
|
||||
this.onSessionCreated.emit(event);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
ParticipantNameDirective
|
||||
} from './videoconference.directive';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
MinimalDirective,
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
import { Directive, AfterViewInit, OnDestroy, Input, ElementRef } from '@angular/core';
|
||||
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({
|
||||
selector: 'ov-videoconference[participantPanelItemMuteButton], ov-participant-panel-item[muteButton]'
|
||||
})
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core';
|
||||
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({
|
||||
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({
|
||||
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({
|
||||
selector: 'ov-videoconference[streamSettingsButton], ov-stream[settingsButton]'
|
||||
})
|
||||
|
|
|
@ -1,21 +1,46 @@
|
|||
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
|
||||
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({
|
||||
selector: 'ov-videoconference[toolbarScreenshareButton], ov-toolbar[screenshareButton]'
|
||||
})
|
||||
export class ToolbarScreenshareButtonDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarScreenshareButton(value: boolean) {
|
||||
this.screenshareValue = value;
|
||||
this.update(this.screenshareValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set screenshareButton(value: boolean) {
|
||||
this.screenshareValue = value;
|
||||
this.update(this.screenshareValue);
|
||||
}
|
||||
|
||||
screenshareValue: boolean = true;
|
||||
private screenshareValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -25,33 +50,58 @@ export class ToolbarScreenshareButtonDirective implements AfterViewInit, OnDestr
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
|
||||
private clear() {
|
||||
this.screenshareValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.screenshareButton.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarFullscreenButton], ov-toolbar[fullscreenButton]'
|
||||
})
|
||||
export class ToolbarFullscreenButtonDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarFullscreenButton(value: boolean) {
|
||||
this.fullscreenValue = value;
|
||||
this.update(this.fullscreenValue);
|
||||
}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set fullscreenButton(value: boolean) {
|
||||
this.fullscreenValue = value;
|
||||
this.update(this.fullscreenValue);
|
||||
}
|
||||
|
||||
fullscreenValue: boolean = true;
|
||||
private fullscreenValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -60,33 +110,57 @@ export class ToolbarFullscreenButtonDirective implements AfterViewInit, OnDestro
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.fullscreenValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.fullscreenButton.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarLeaveButton], ov-toolbar[leaveButton]'
|
||||
})
|
||||
export class ToolbarLeaveButtonDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarLeaveButton(value: boolean) {
|
||||
this.leaveValue = value;
|
||||
this.update(this.leaveValue);
|
||||
}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set leaveButton(value: boolean) {
|
||||
this.leaveValue = value;
|
||||
this.update(this.leaveValue);
|
||||
}
|
||||
|
||||
leaveValue: boolean = true;
|
||||
private leaveValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -96,33 +170,58 @@ export class ToolbarLeaveButtonDirective implements AfterViewInit, OnDestroy {
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.leaveValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.leaveButton.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarParticipantsPanelButton], ov-toolbar[participantsPanelButton]'
|
||||
})
|
||||
export class ToolbarParticipantsPanelButtonDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarParticipantsPanelButton(value: boolean) {
|
||||
this.participantsPanelValue = value;
|
||||
this.update(this.participantsPanelValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set participantsPanelButton(value: boolean) {
|
||||
this.participantsPanelValue = value;
|
||||
this.update(this.participantsPanelValue);
|
||||
}
|
||||
|
||||
participantsPanelValue: boolean = true;
|
||||
private participantsPanelValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -132,32 +231,56 @@ export class ToolbarParticipantsPanelButtonDirective implements AfterViewInit, O
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.participantsPanelValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.participantsPanelButton.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarChatPanelButton], ov-toolbar[chatPanelButton]'
|
||||
})
|
||||
export class ToolbarChatPanelButtonDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarChatPanelButton(value: boolean) {
|
||||
this.toolbarChatPanelValue = value;
|
||||
this.update(this.toolbarChatPanelValue);
|
||||
}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set chatPanelButton(value: boolean) {
|
||||
this.toolbarChatPanelValue = value;
|
||||
this.update(this.toolbarChatPanelValue);
|
||||
}
|
||||
toolbarChatPanelValue: boolean = true;
|
||||
private toolbarChatPanelValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -167,33 +290,57 @@ export class ToolbarChatPanelButtonDirective implements AfterViewInit, OnDestroy
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.toolbarChatPanelValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.chatPanelButton.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarDisplaySessionName], ov-toolbar[displaySessionName]'
|
||||
})
|
||||
export class ToolbarDisplaySessionNameDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarDisplaySessionName(value: boolean) {
|
||||
this.displaySessionValue = value;
|
||||
this.update(this.displaySessionValue);
|
||||
}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set displaySessionName(value: boolean) {
|
||||
this.displaySessionValue = value;
|
||||
this.update(this.displaySessionValue);
|
||||
}
|
||||
|
||||
displaySessionValue: boolean = true;
|
||||
private displaySessionValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -203,33 +350,57 @@ export class ToolbarDisplaySessionNameDirective implements AfterViewInit, OnDest
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.displaySessionValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.displaySessionName.getValue() !== 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({
|
||||
selector: 'ov-videoconference[toolbarDisplayLogo], ov-toolbar[displayLogo]'
|
||||
})
|
||||
export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set toolbarDisplayLogo(value: boolean) {
|
||||
this.displayLogoValue = value;
|
||||
this.update(this.displayLogoValue);
|
||||
}
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set displayLogo(value: boolean) {
|
||||
this.displayLogoValue = value;
|
||||
this.update(this.displayLogoValue);
|
||||
}
|
||||
|
||||
displayLogoValue: boolean = true;
|
||||
private displayLogoValue: boolean = true;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
@ -239,12 +410,12 @@ export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
|||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
private clear() {
|
||||
this.displayLogoValue = true;
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
update(value: boolean) {
|
||||
private update(value: boolean) {
|
||||
if (this.libService.displayLogo.getValue() !== value) {
|
||||
this.libService.displayLogo.next(value);
|
||||
}
|
||||
|
@ -253,7 +424,10 @@ export class ToolbarDisplayLogoDirective implements AfterViewInit, OnDestroy {
|
|||
|
||||
// * Private directives *
|
||||
|
||||
// Load default OpenVidu logo if custom one is not exist
|
||||
/**
|
||||
* Load default OpenVidu logo if custom one is not exist
|
||||
* @internal
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'img[ovLogo]'
|
||||
})
|
||||
|
|
|
@ -1,21 +1,49 @@
|
|||
import { Directive, Input, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
||||
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({
|
||||
selector: 'ov-videoconference[minimal]'
|
||||
})
|
||||
export class MinimalDirective implements OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set minimal(value: boolean) {
|
||||
this.update(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
clear() {
|
||||
this.update(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
update(value: boolean) {
|
||||
if (this.libService.minimal.getValue() !== 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({
|
||||
selector: 'ov-videoconference[participantName]'
|
||||
})
|
||||
export class ParticipantNameDirective implements OnInit {
|
||||
// Avoiding update participantName dynamically.
|
||||
// The participantName must be updated from UI
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() participantName: string;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.update(this.participantName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
clear() {
|
||||
this.update('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
update(value: string) {
|
||||
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({
|
||||
selector: 'ov-videoconference[prejoin]'
|
||||
})
|
||||
export class PrejoinDirective implements OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set prejoin(value: boolean) {
|
||||
this.update(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
clear() {
|
||||
this.update(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
update(value: boolean) {
|
||||
if (this.libService.prejoin.getValue() !== 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({
|
||||
selector: 'ov-videoconference[videoMuted]'
|
||||
})
|
||||
export class VideoMutedDirective implements OnDestroy {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set videoMuted(value: boolean) {
|
||||
this.update(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
clear() {
|
||||
this.update(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
update(value: boolean) {
|
||||
if (this.libService.videoMuted.getValue() !== 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({
|
||||
selector: 'ov-videoconference[audioMuted]'
|
||||
})
|
||||
export class AudioMutedDirective implements OnDestroy {
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@Input() set audioMuted(value: boolean) {
|
||||
this.update(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(public elementRef: ElementRef, private libService: OpenViduAngularConfigService) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
clear() {
|
||||
this.update(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
update(value: boolean) {
|
||||
if (this.libService.audioMuted.getValue() !== value) {
|
||||
this.libService.audioMuted.next(value);
|
||||
|
|
|
@ -1,19 +1,71 @@
|
|||
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({
|
||||
selector: '[ovToolbar]'
|
||||
})
|
||||
export class ToolbarDirective {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
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({
|
||||
selector: '[ovToolbarAdditionalButtons]'
|
||||
})
|
||||
export class ToolbarAdditionalButtonsDirective {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
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({
|
||||
selector: '[ovPanel]'
|
||||
})
|
||||
|
@ -21,6 +73,32 @@ export class PanelDirective {
|
|||
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({
|
||||
selector: '[ovChatPanel]'
|
||||
})
|
||||
|
@ -56,10 +134,37 @@ export class LayoutDirective {
|
|||
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({
|
||||
selector: '[ovStream]'
|
||||
})
|
||||
export class StreamDirective {
|
||||
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';
|
||||
|
||||
/** Error when invalid control is dirty, touched, or submitted. */
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class NicknameMatcher implements ErrorStateMatcher {
|
||||
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||
const isSubmitted = form && form.submitted;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
export enum AvatarType {
|
||||
DEFAULT = 'default',
|
||||
CAPTURED = 'captured'
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ChatMessage {
|
||||
isLocal: boolean;
|
||||
nickname: string;
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface CustomDevice {
|
||||
label: string;
|
||||
device: string;
|
||||
type?: CameraType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum CameraType {
|
||||
FRONT = 'FRONT',
|
||||
BACK = 'BACK'
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum DeviceType {
|
||||
AUDIO_INPUT = 'audioinput',
|
||||
VIDEO_INPUT = 'videoinput'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum VideoSizeIcon {
|
||||
BIG = 'zoom_in',
|
||||
NORMAL = 'zoom_out'
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum LayoutClass {
|
||||
ROOT_ELEMENT = 'OT_root',
|
||||
BIG_ELEMENT = 'OV_big',
|
||||
|
@ -6,15 +9,17 @@ export enum LayoutClass {
|
|||
NO_SIZE_ELEMENT = 'no-size'
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum SidenavMode {
|
||||
OVER = 'over',
|
||||
SIDE = 'side'
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* @internal
|
||||
*/
|
||||
|
||||
export interface OpenViduLayoutOptions {
|
||||
/**
|
||||
* The narrowest ratio that will be used (*2x3* by default)
|
||||
|
@ -70,6 +75,9 @@ export interface OpenViduLayoutOptions {
|
|||
bigFirst: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class OpenViduLayout {
|
||||
/**
|
||||
* @hidden
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { Autolinker, AutolinkerConfig, HashtagMatch } from 'autolinker';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const AUTOLINKER_CFGS: AutolinkerConfig = {
|
||||
urls: {
|
||||
schemeMatches: true,
|
||||
|
@ -20,6 +23,9 @@ const AUTOLINKER_CFGS: AutolinkerConfig = {
|
|||
decodePercentEncoding: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class Linkifier {
|
||||
private autolinker: Autolinker;
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ILogger {
|
||||
d(...args: any[]): void;
|
||||
w(...args: any[]): void;
|
||||
e(...args: any[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ILogService {
|
||||
get(name: string): ILogger;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum MenuType {
|
||||
CHAT = 'chat',
|
||||
PARTICIPANTS = 'participants'
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { MatSnackBarConfig } from '@angular/material/snack-bar';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface INotificationOptions {
|
||||
message: string;
|
||||
buttonActionText?: string;
|
||||
|
|
|
@ -2,19 +2,52 @@ import { Publisher, StreamManager } from 'openvidu-browser';
|
|||
import { VideoType } from './video-type.model';
|
||||
|
||||
export interface StreamModel {
|
||||
/**
|
||||
* Whether the stream is available or not
|
||||
*/
|
||||
connected: boolean;
|
||||
/**
|
||||
* The stream type.{@link 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;
|
||||
/**
|
||||
* Whether the stream is enlarged or not
|
||||
*/
|
||||
videoEnlarged: boolean;
|
||||
/**
|
||||
* Unique identifier of the stream
|
||||
*/
|
||||
connectionId: string;
|
||||
participant?: ParticipantAbstractModel
|
||||
/**
|
||||
* The participant object
|
||||
*/
|
||||
participant?: ParticipantAbstractModel;
|
||||
}
|
||||
|
||||
export interface ParticipantProperties {
|
||||
/**
|
||||
* Whether the participant is local or not
|
||||
*/
|
||||
local: boolean;
|
||||
/**
|
||||
* The participant nickname
|
||||
*/
|
||||
nickname: string;
|
||||
/**
|
||||
* Unique identifier of the participant
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* The participant color profile
|
||||
*/
|
||||
colorProfile?: string;
|
||||
/**
|
||||
* Whether the participant is muted forcibly or not
|
||||
*/
|
||||
isMutedForcibly?: boolean;
|
||||
}
|
||||
|
||||
|
@ -30,7 +63,7 @@ export abstract class ParticipantAbstractModel {
|
|||
this.id = props.id ? props.id : new Date().getTime().toString();
|
||||
this.local = props.local;
|
||||
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;
|
||||
let streamModel: StreamModel = {
|
||||
connected: model ? model.connected : true,
|
||||
|
@ -43,43 +76,68 @@ export abstract class ParticipantAbstractModel {
|
|||
this.streams.set(streamModel.type, streamModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
addConnection(streamModel: StreamModel) {
|
||||
streamModel.participant = this;
|
||||
this.streams.set(streamModel.type, streamModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public isCameraAudioActive(): boolean {
|
||||
const cameraConnection = this.getCameraConnection();
|
||||
if(cameraConnection) {
|
||||
if (cameraConnection) {
|
||||
return cameraConnection.connected && cameraConnection.streamManager?.stream?.audioActive;
|
||||
}
|
||||
return this.isScreenAudioActive();;
|
||||
return this.isScreenAudioActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public isCameraVideoActive(): boolean {
|
||||
const cameraConnection = this.getCameraConnection();
|
||||
return cameraConnection?.connected && cameraConnection?.streamManager?.stream?.videoActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isScreenAudioActive(): boolean {
|
||||
const screenConnection = this.getScreenConnection();
|
||||
if(screenConnection){
|
||||
if (screenConnection) {
|
||||
return screenConnection?.connected && screenConnection?.streamManager?.stream?.audioActive;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
hasConnectionType(type: VideoType): boolean {
|
||||
return this.streams.has(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public getCameraConnection(): StreamModel {
|
||||
return this.streams.get(VideoType.CAMERA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public getScreenConnection(): StreamModel {
|
||||
return this.streams.get(VideoType.SCREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getConnectionTypesActive(): VideoType[] {
|
||||
let connType = [];
|
||||
if (this.isCameraActive()) connType.push(VideoType.CAMERA);
|
||||
|
@ -88,116 +146,168 @@ export abstract class ParticipantAbstractModel {
|
|||
return connType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setCameraConnectionId(connectionId: string) {
|
||||
this.getCameraConnection().connectionId = connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setScreenConnectionId(connectionId: string) {
|
||||
this.getScreenConnection().connectionId = connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
removeConnection(connectionId: string): StreamModel {
|
||||
const removeStream = this.getConnectionById(connectionId);
|
||||
this.streams.delete(removeStream.type);
|
||||
return removeStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
hasConnectionId(connectionId: string): boolean {
|
||||
return Array.from(this.streams.values()).some((conn) => conn.connectionId === connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getConnectionById(connectionId: string): StreamModel {
|
||||
return Array.from(this.streams.values()).find((conn) => conn.connectionId === connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getAvailableConnections(): StreamModel[] {
|
||||
return Array.from(this.streams.values()).filter((conn) => conn.connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isLocal(): boolean {
|
||||
return this.local;
|
||||
// return Array.from(this.streams.values()).every((conn) => conn.local);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setNickname(nickname: string) {
|
||||
this.nickname = nickname;
|
||||
// this.streams.forEach((conn) => {
|
||||
// if (conn.type === VideoType.CAMERA) {
|
||||
// conn.nickname = nickname;
|
||||
// } else {
|
||||
// conn.nickname = `${nickname}_${conn.type}`;
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getNickname() {
|
||||
return this.nickname;
|
||||
}
|
||||
|
||||
// getCameraNickname(): string {
|
||||
// return this.getCameraConnection()?.nickname;
|
||||
// }
|
||||
|
||||
// getScreenNickname(): string {
|
||||
// return this.getScreenConnection()?.nickname;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setCameraPublisher(publisher: Publisher) {
|
||||
const cameraConnection = this.getCameraConnection();
|
||||
if (cameraConnection) cameraConnection.streamManager = publisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setScreenPublisher(publisher: Publisher) {
|
||||
const screenConnection = this.getScreenConnection();
|
||||
if (screenConnection) screenConnection.streamManager = publisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setPublisher(connType: VideoType, publisher: StreamManager) {
|
||||
const connection = this.streams.get(connType);
|
||||
if(connection) {
|
||||
if (connection) {
|
||||
connection.streamManager = publisher;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isCameraActive(): boolean {
|
||||
return this.getCameraConnection()?.connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
enableCamera() {
|
||||
const cameraConnection = this.getCameraConnection();
|
||||
if (cameraConnection) cameraConnection.connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
disableCamera() {
|
||||
const cameraConnection = this.getCameraConnection();
|
||||
if (cameraConnection) cameraConnection.connected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isScreenActive(): boolean {
|
||||
return this.getScreenConnection()?.connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
enableScreen() {
|
||||
const screenConnection = this.getScreenConnection();
|
||||
if (screenConnection) screenConnection.connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
disableScreen() {
|
||||
const screenConnection = this.getScreenConnection();
|
||||
if (screenConnection) screenConnection.connected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setAllVideoEnlarged(enlarged: boolean) {
|
||||
this.streams.forEach((conn) => (conn.videoEnlarged = enlarged));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setCameraEnlarged(enlarged: boolean) {
|
||||
this.streams.get(VideoType.CAMERA).videoEnlarged = enlarged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setScreenEnlarged(enlarged: boolean) {
|
||||
this.streams.get(VideoType.SCREEN).videoEnlarged = enlarged;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
toggleVideoEnlarged(connectionId: string) {
|
||||
this.streams.forEach((conn) => {
|
||||
if (conn.connectionId === connectionId) {
|
||||
|
@ -206,17 +316,22 @@ export abstract class ParticipantAbstractModel {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
someHasVideoEnlarged(): boolean {
|
||||
return Array.from(this.streams.values()).some((conn) => conn.videoEnlarged);
|
||||
}
|
||||
|
||||
setMutedForcibly(muted: boolean){
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMutedForcibly(muted: boolean) {
|
||||
this.isMutedForcibly = muted;
|
||||
}
|
||||
}
|
||||
|
||||
export class ParticipantModel extends ParticipantAbstractModel {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class ParticipantModel extends ParticipantAbstractModel {}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum Signal {
|
||||
NICKNAME_CHANGED = 'nicknameChanged',
|
||||
CHAT = 'chat'
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum Storage{
|
||||
USER_NICKNAME = 'openviduCallNickname',
|
||||
VIDEO_DEVICE = 'openviduCallVideoDevice',
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface TokenModel {
|
||||
webcam: string;
|
||||
screen: string;
|
||||
}
|
|
@ -4,6 +4,9 @@ export enum VideoType {
|
|||
CUSTOM = 'CUSTOM'
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum ScreenType {
|
||||
WINDOW = 'window',
|
||||
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 { Linkifier } from '../models/linkifier.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Pipe({ name: 'linkify' })
|
||||
export class LinkifyPipe implements PipeTransform {
|
||||
private linkifer: Linkifier;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { StreamModel, ParticipantAbstractModel } from '../models/participant.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Pipe({ name: 'streams' })
|
||||
export class ParticipantStreamsPipe implements PipeTransform {
|
||||
constructor() {}
|
||||
|
@ -21,6 +24,9 @@ export class ParticipantStreamsPipe implements PipeTransform {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Pipe({ name: 'streamTypesEnabled' })
|
||||
export class StreamTypesEnabledPipe implements PipeTransform {
|
||||
constructor() {}
|
||||
|
|
|
@ -5,6 +5,9 @@ import { DialogTemplateComponent } from '../../components/material/dialog.compon
|
|||
|
||||
import { INotificationOptions } from '../../models/notification-options.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {CdkOverlayContainer } from '../../config/custom-cdk-overlay';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -14,6 +14,9 @@ import { SidenavMenuService } from '../sidenav-menu/sidenav-menu.service';
|
|||
import { ParticipantService } from '../participant/participant.service';
|
||||
import { MenuType } from '../../models/menu.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -4,7 +4,9 @@ import { OpenViduAngularConfig, ParticipantFactoryFunction } from '../../config/
|
|||
|
||||
// import { version } from '../../../../package.json';
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable()
|
||||
export class OpenViduAngularConfigService {
|
||||
private configuration: OpenViduAngularConfig;
|
||||
|
@ -51,7 +53,7 @@ export class OpenViduAngularConfigService {
|
|||
constructor(@Inject('OPENVIDU_ANGULAR_CONFIG') config: OpenViduAngularConfig) {
|
||||
this.configuration = config;
|
||||
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.participantNameObs = this.participantName.asObservable();
|
||||
this.prejoinObs = this.prejoin.asObservable();
|
||||
|
@ -85,7 +87,7 @@ export class OpenViduAngularConfigService {
|
|||
// }
|
||||
|
||||
hasParticipantFactory(): boolean {
|
||||
return typeof this.getConfig().participantFactory === "function";
|
||||
return typeof this.getConfig().participantFactory === 'function';
|
||||
}
|
||||
|
||||
getParticipantFactory(): ParticipantFactoryFunction {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CameraType, IDevice } from '../../models/device.model';
|
||||
import { CameraType, CustomDevice } from '../../models/device.model';
|
||||
|
||||
@Injectable()
|
||||
export class DeviceServiceMock {
|
||||
audioDevice: IDevice = {
|
||||
audioDevice: CustomDevice = {
|
||||
label: 'audio',
|
||||
device: 'mockDevice'
|
||||
};
|
||||
videodevice: IDevice = {
|
||||
videodevice: CustomDevice = {
|
||||
label: 'video',
|
||||
device: 'mockDevice',
|
||||
type: CameraType.FRONT
|
||||
|
@ -17,11 +17,11 @@ export class DeviceServiceMock {
|
|||
|
||||
async initDevices() {}
|
||||
|
||||
getCamSelected(): IDevice {
|
||||
getCamSelected(): CustomDevice {
|
||||
return this.videodevice;
|
||||
}
|
||||
|
||||
getMicSelected(): IDevice {
|
||||
getMicSelected(): CustomDevice {
|
||||
return this.audioDevice;
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,11 @@ export class DeviceServiceMock {
|
|||
return false;
|
||||
}
|
||||
|
||||
getCameras(): IDevice[] {
|
||||
getCameras(): CustomDevice[] {
|
||||
return [this.videodevice];
|
||||
}
|
||||
|
||||
getMicrophones(): IDevice[] {
|
||||
getMicrophones(): CustomDevice[] {
|
||||
return [this.audioDevice];
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ import { LoggerService } from '../logger/logger.service';
|
|||
import { PlatformService } from '../platform/platform.service';
|
||||
import { StorageService } from '../storage/storage.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
@ -60,7 +63,7 @@ export class DeviceService {
|
|||
this.microphones = customDevices.microphones;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { LayoutClass } from '../../models/layout.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -3,6 +3,9 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|||
import { LayoutClass, OpenViduLayout, OpenViduLayoutOptions } from '../../models/layout.model';
|
||||
import { DocumentService } from '../document/document.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -3,6 +3,9 @@ import { ILogService } from '../../models/logger.model';
|
|||
|
||||
import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -33,6 +33,9 @@ export class OpenViduService {
|
|||
protected audioSource = undefined;
|
||||
protected log: ILogger;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
constructor(
|
||||
protected openviduAngularConfigSrv: OpenViduAngularConfigService,
|
||||
protected platformService: PlatformService,
|
||||
|
@ -43,6 +46,9 @@ export class OpenViduService {
|
|||
this.log = this.loggerSrv.get('OpenViduService');
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
initialize() {
|
||||
this.OV = new OpenVidu();
|
||||
if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode();
|
||||
|
@ -60,22 +66,37 @@ export class OpenViduService {
|
|||
return this.getWebcamSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getWebcamSession(): Session {
|
||||
return this.webcamSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isWebcamSessionConnected(): boolean {
|
||||
return !!this.webcamSession.capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getScreenSession(): Session {
|
||||
return this.screenSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isScreenSessionConnected(): boolean {
|
||||
return !!this.screenSession.capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
async connectSession(session: Session, token: string): Promise<void> {
|
||||
if (!!token && session) {
|
||||
const nickname = this.participantService.getMyNickname();
|
||||
|
@ -101,6 +122,9 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
disconnect() {
|
||||
this.disconnectSession(this.webcamSession);
|
||||
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.
|
||||
*/
|
||||
async initDefaultPublisher(targetElement: string | HTMLElement): Promise<Publisher> {
|
||||
|
@ -158,11 +183,17 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
async initPublisher(targetElement: string | HTMLElement, properties: PublisherProperties): Promise<Publisher> {
|
||||
this.log.d('Initializing publisher with properties: ', properties);
|
||||
return await this.OV.initPublisherAsync(targetElement, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
async publish(publisher: Publisher): Promise<void> {
|
||||
if (!!publisher) {
|
||||
if (publisher === this.participantService.getMyCameraPublisher()) {
|
||||
|
@ -179,6 +210,9 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
unpublish(publisher: Publisher): void {
|
||||
if (!!publisher) {
|
||||
if (publisher === this.participantService.getMyCameraPublisher()) {
|
||||
|
@ -190,6 +224,9 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
publishVideo(publisher: Publisher, value: boolean): void {
|
||||
if (!!publisher) {
|
||||
publisher.publishVideo(value);
|
||||
|
@ -197,6 +234,9 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
publishAudio(publisher: Publisher, value: boolean): void {
|
||||
if (!!publisher) {
|
||||
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> {
|
||||
const { videoSource, audioSource, mirror } = properties;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
@ -240,6 +283,9 @@ export class OpenViduService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
sendSignal(type: Signal, connections?: Connection[], data?: any): void {
|
||||
const signalOptions: SignalOptions = {
|
||||
data: JSON.stringify(data),
|
||||
|
@ -255,6 +301,9 @@ export class OpenViduService {
|
|||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
async replaceTrack(videoType: VideoType, props: PublisherProperties) {
|
||||
try {
|
||||
this.log.d(`Replacing ${videoType} track`, props);
|
||||
|
@ -346,6 +395,9 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
needSendNicknameSignal(): boolean {
|
||||
let oldNickname: string;
|
||||
try {
|
||||
|
@ -357,6 +409,9 @@ export class OpenViduService {
|
|||
return oldNickname !== this.participantService.getMyNickname();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isMyOwnConnection(connectionId: string): boolean {
|
||||
return (
|
||||
this.webcamSession?.connection?.connectionId === connectionId || this.screenSession?.connection?.connectionId === connectionId
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { Publisher } from 'openvidu-browser/lib/OpenVidu/Publisher';
|
||||
import { UserModel } from '../../models/user.model';
|
||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ParticipantServiceMock {
|
||||
OVUsers: Observable<UserModel[]>;
|
||||
OVUsers: Observable<ParticipantAbstractModel[]>;
|
||||
screenShareState: 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 _webcamVideoActive = <BehaviorSubject<boolean>>new BehaviorSubject(true);
|
||||
|
||||
|
|
|
@ -11,11 +11,17 @@ import { LoggerService } from '../logger/logger.service';
|
|||
providedIn: 'root'
|
||||
})
|
||||
export class ParticipantService {
|
||||
//Local participants observables
|
||||
/**
|
||||
* @internal
|
||||
* Local participants observables
|
||||
*/
|
||||
localParticipantObs: Observable<ParticipantAbstractModel>;
|
||||
protected _localParticipant = <BehaviorSubject<ParticipantAbstractModel>>new BehaviorSubject(null);
|
||||
|
||||
//Remote participants observable
|
||||
/**
|
||||
* @internal
|
||||
* Remote participants observables
|
||||
*/
|
||||
remoteParticipantsObs: Observable<ParticipantAbstractModel[]>;
|
||||
protected _remoteParticipants = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]);
|
||||
|
||||
|
@ -24,6 +30,9 @@ export class ParticipantService {
|
|||
|
||||
protected log: ILogger;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
constructor(protected openviduAngularConfigSrv: OpenViduAngularConfigService, protected loggerSrv: LoggerService) {
|
||||
this.log = this.loggerSrv.get('ParticipantService');
|
||||
|
||||
|
@ -31,7 +40,10 @@ export class ParticipantService {
|
|||
this.remoteParticipantsObs = this._remoteParticipants.asObservable();
|
||||
}
|
||||
|
||||
initLocalParticipant(props: ParticipantProperties) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
initLocalParticipant(props: ParticipantProperties) {
|
||||
this.localParticipant = this.newParticipant(props);
|
||||
this.updateLocalParticipant();
|
||||
}
|
||||
|
@ -40,13 +52,22 @@ export class ParticipantService {
|
|||
return this.localParticipant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getMyCameraPublisher(): Publisher {
|
||||
return <Publisher>this.localParticipant.getCameraConnection().streamManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMyCameraPublisher(publisher: Publisher) {
|
||||
this.localParticipant.setCameraPublisher(publisher);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMyCameraConnectionId(connectionId: string) {
|
||||
this.localParticipant.setCameraConnectionId(connectionId);
|
||||
}
|
||||
|
@ -58,26 +79,39 @@ export class ParticipantService {
|
|||
return <Publisher>this.localParticipant.getScreenConnection()?.streamManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMyScreenPublisher(publisher: Publisher) {
|
||||
this.localParticipant.setScreenPublisher(publisher);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMyScreenConnectionId(connectionId: string) {
|
||||
this.localParticipant.setScreenConnectionId(connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
enableWebcamStream() {
|
||||
this.localParticipant.enableCamera();
|
||||
this.updateLocalParticipant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
disableWebcamStream() {
|
||||
this.localParticipant.disableCamera();
|
||||
this.updateLocalParticipant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
activeMyScreenShare(screenPublisher: Publisher) {
|
||||
this.log.d('Enabling screen publisher');
|
||||
|
||||
|
@ -96,16 +130,24 @@ export class ParticipantService {
|
|||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
disableScreenStream() {
|
||||
this.localParticipant.disableScreen();
|
||||
this.updateLocalParticipant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setMyNickname(nickname: string) {
|
||||
this.localParticipant.setNickname(nickname);
|
||||
this.updateLocalParticipant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getMyNickname(): string {
|
||||
return this.localParticipant.nickname;
|
||||
}
|
||||
|
@ -113,13 +155,13 @@ export class ParticipantService {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
|
||||
toggleMyVideoEnlarged(connectionId: string) {
|
||||
this.localParticipant.toggleVideoEnlarged(connectionId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
resetMyStreamsToNormalSize() {
|
||||
if (this.localParticipant.someHasVideoEnlarged()) {
|
||||
this.localParticipant.setAllVideoEnlarged(false);
|
||||
|
@ -127,6 +169,9 @@ export class ParticipantService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
clear() {
|
||||
this.disableScreenStream();
|
||||
// this.localParticipant = this.newParticipant();
|
||||
|
@ -137,34 +182,58 @@ export class ParticipantService {
|
|||
this.updateLocalParticipant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isMyCameraActive(): boolean {
|
||||
return this.localParticipant.isCameraActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isMyScreenActive(): boolean {
|
||||
return this.localParticipant.isScreenActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isOnlyMyCameraActive(): boolean {
|
||||
return this.isMyCameraActive() && !this.isMyScreenActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isOnlyMyScreenActive(): boolean {
|
||||
return this.isMyScreenActive() && !this.isMyCameraActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
haveICameraAndScreenActive(): boolean {
|
||||
return this.isMyCameraActive() && this.isMyScreenActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
hasCameraVideoActive(): boolean {
|
||||
return this.localParticipant.isCameraVideoActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
hasCameraAudioActive(): boolean {
|
||||
return this.localParticipant?.isCameraAudioActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
hasScreenAudioActive(): boolean {
|
||||
return this.localParticipant.isScreenAudioActive();
|
||||
}
|
||||
|
@ -177,14 +246,16 @@ export class ParticipantService {
|
|||
* REMOTE USERS
|
||||
*/
|
||||
|
||||
addRemoteConnection(connectionId:string, data: string, subscriber: Subscriber) {
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
addRemoteConnection(connectionId: string, data: string, subscriber: Subscriber) {
|
||||
const type: VideoType = this.getTypeConnectionData(data);
|
||||
const streamModel: StreamModel = {
|
||||
type,
|
||||
videoEnlarged: type === VideoType.SCREEN,
|
||||
streamManager: subscriber,
|
||||
connected: true,
|
||||
connected: true,
|
||||
connectionId
|
||||
};
|
||||
|
||||
|
@ -195,12 +266,12 @@ export class ParticipantService {
|
|||
const participantAdded = this.getRemoteParticipantById(participantId);
|
||||
if (!!participantAdded) {
|
||||
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');
|
||||
participantAdded.setPublisher(streamModel.type, subscriber);
|
||||
} else {
|
||||
this.log.d('Participant has not publisher, adding it');
|
||||
if(streamModel.type === VideoType.SCREEN) {
|
||||
if (streamModel.type === VideoType.SCREEN) {
|
||||
this.resetRemoteStreamsToNormalSize();
|
||||
this.resetMyStreamsToNormalSize();
|
||||
}
|
||||
|
@ -212,18 +283,28 @@ export class ParticipantService {
|
|||
nickname: this.getNicknameFromConnectionData(data),
|
||||
local: false,
|
||||
id: participantId
|
||||
}
|
||||
};
|
||||
const remoteParticipant = this.newParticipant(props, streamModel);
|
||||
this.remoteParticipants.push(remoteParticipant);
|
||||
}
|
||||
this.updateRemoteParticipants();
|
||||
}
|
||||
|
||||
getRemoteParticipants(): ParticipantAbstractModel[] {
|
||||
return this.remoteParticipants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
resetRemoteStreamsToNormalSize() {
|
||||
this.remoteParticipants.forEach(participant => participant.setAllVideoEnlarged(false));
|
||||
this.remoteParticipants.forEach((participant) => participant.setAllVideoEnlarged(false));
|
||||
this.updateRemoteParticipants();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
removeConnectionByConnectionId(connectionId: string) {
|
||||
this.log.w('Deleting connection: ', connectionId);
|
||||
let participant = null;
|
||||
|
@ -240,13 +321,13 @@ export class ParticipantService {
|
|||
// Remove participants without connections
|
||||
this.remoteParticipants = this.remoteParticipants.filter((p) => p !== participant);
|
||||
}
|
||||
if(removeStream.type === VideoType.SCREEN){
|
||||
const remoteScreens = this.remoteParticipants.filter(p => p.isScreenActive());
|
||||
if(remoteScreens.length > 0){
|
||||
if (removeStream.type === VideoType.SCREEN) {
|
||||
const remoteScreens = this.remoteParticipants.filter((p) => p.isScreenActive());
|
||||
if (remoteScreens.length > 0) {
|
||||
// Enlarging the last screen connection active
|
||||
const lastScreenActive = remoteScreens[remoteScreens.length -1];
|
||||
const lastScreenActive = remoteScreens[remoteScreens.length - 1];
|
||||
lastScreenActive.setScreenEnlarged(true);
|
||||
} else if(this.localParticipant.isScreenActive()) {
|
||||
} else if (this.localParticipant.isScreenActive()) {
|
||||
// Enlarging my screen if thereare not any remote screen active
|
||||
this.localParticipant.setScreenEnlarged(true);
|
||||
}
|
||||
|
@ -255,6 +336,9 @@ export class ParticipantService {
|
|||
this.updateRemoteParticipants();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getRemoteParticipantByConnectionId(connectionId: string): ParticipantAbstractModel {
|
||||
return this.remoteParticipants.find((p) => p.hasConnectionId(connectionId));
|
||||
}
|
||||
|
@ -262,15 +346,24 @@ export class ParticipantService {
|
|||
protected getRemoteParticipantById(id: string): ParticipantAbstractModel {
|
||||
return this.remoteParticipants.find((p) => p.id === id);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
someoneIsSharingScreen(): boolean {
|
||||
return this.remoteParticipants.some((p) => p.someHasVideoEnlarged());
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
toggleRemoteVideoEnlarged(connectionId: string) {
|
||||
const p = this.getRemoteParticipantByConnectionId(connectionId);
|
||||
p.toggleVideoEnlarged(connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getNicknameFromConnectionData(data: string): string {
|
||||
try {
|
||||
return JSON.parse(data).clientData;
|
||||
|
@ -279,6 +372,9 @@ export class ParticipantService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setRemoteNickname(connectionId: string, nickname: string) {
|
||||
const participant = this.getRemoteParticipantByConnectionId(connectionId);
|
||||
if (participant) {
|
||||
|
@ -308,8 +404,7 @@ export class ParticipantService {
|
|||
}
|
||||
|
||||
protected newParticipant(props: ParticipantProperties, streamModel?: StreamModel) {
|
||||
|
||||
if(this.openviduAngularConfigSrv.hasParticipantFactory()){
|
||||
if (this.openviduAngularConfigSrv.hasParticipantFactory()) {
|
||||
return this.openviduAngularConfigSrv.getParticipantFactory().apply(this, [props, streamModel]);
|
||||
}
|
||||
return new ParticipantModel(props, streamModel);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -4,6 +4,9 @@ import { ILogger } from '../../models/logger.model';
|
|||
import { MenuType } from '../../models/menu.model';
|
||||
import { LoggerService } from '../logger/logger.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -3,6 +3,9 @@ import { ILogger } from '../../models/logger.model';
|
|||
import { LoggerService } from '../logger/logger.service';
|
||||
import { Storage } from '../../models/storage.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Injectable({
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* **OpenviduWebComponentComponent** is a wrapped of the {@link VideoconferenceComponent} which allows to generate and export the OpenVidu Webcomponent
|
||||
*/
|
||||
@Component({
|
||||
template: `
|
||||
<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>
|
||||
`
|
||||
templateUrl: './openvidu-webcomponent.component.html'
|
||||
})
|
||||
export class OpenviduWebComponentComponent implements OnInit {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_tokens: TokenModel;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_minimal: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_participantName: string;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_prejoin: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_videoMuted: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_audioMuted: boolean = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarScreenshareButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarFullscreenButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarLeaveButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarChatPanelButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarParticipantsPanelButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarDisplayLogo: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_toolbarDisplaySessionName: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_streamDisplayParticipantName: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_streamDisplayAudioDetection: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_streamSettingsButton: boolean = true;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_participantPanelItemMuteButton: boolean = true;
|
||||
|
||||
@Input() set minimal(value: string | boolean) {
|
||||
|
@ -122,9 +146,15 @@ export class OpenviduWebComponentComponent implements OnInit {
|
|||
@Output() onSessionCreated = new EventEmitter<any>();
|
||||
@Output() onParticipantCreated = new EventEmitter<any>();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
success: boolean = false;
|
||||
private log: ILogger;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
constructor(private loggerService: LoggerService, private host: ElementRef, private openviduService: OpenViduService) {
|
||||
this.log = this.loggerService.get('WebComponent');
|
||||
this.host.nativeElement.leaveSession = this.leaveSession.bind(this);
|
||||
|
@ -147,37 +177,68 @@ export class OpenviduWebComponentComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onJoinButtonClicked() {
|
||||
this.onJoinButtonClicked.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarLeaveButtonClicked() {
|
||||
this.success = false;
|
||||
this.onToolbarLeaveButtonClicked.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarCameraButtonClicked() {
|
||||
this.onToolbarCameraButtonClicked.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarMicrophoneButtonClicked() {
|
||||
this.onToolbarMicrophoneButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarScreenshareButtonClicked() {
|
||||
this.onToolbarScreenshareButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarParticipantsPanelButtonClicked() {
|
||||
this.onToolbarParticipantsPanelButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarChatPanelButtonClicked() {
|
||||
this.onToolbarChatPanelButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onToolbarFullscreenButtonClicked() {
|
||||
this.onToolbarFullscreenButtonClicked.emit();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onSessionCreated(event: Session) {
|
||||
this.onSessionCreated.emit(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onParticipantCreated(event: ParticipantAbstractModel) {
|
||||
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