mirror of https://github.com/OpenVidu/openvidu.git
openvidu-component: Loaded components dynamically
- For loading components with inputs/outputs directives, has been necessary to use the 'ng-dynamic-component' library because of unsupported on the official Angular issue https://github.com/angular/angular/issues/15360 - Allowed the dynamic components load - Grouped panels into panel componentpull/690/head
parent
e56ac82749
commit
5f0ffb4b3a
|
@ -20,6 +20,7 @@
|
||||||
"@angular/router": "13.0.0",
|
"@angular/router": "13.0.0",
|
||||||
"autolinker": "3.14.3",
|
"autolinker": "3.14.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
"ng-dynamic-component": "^10.1.0",
|
||||||
"openvidu-browser": "2.21.0-beta1",
|
"openvidu-browser": "2.21.0-beta1",
|
||||||
"rxjs": "7.4.0",
|
"rxjs": "7.4.0",
|
||||||
"tslib": "2.3.1",
|
"tslib": "2.3.1",
|
||||||
|
@ -9065,6 +9066,19 @@
|
||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/ng-dynamic-component": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ng-dynamic-component/-/ng-dynamic-component-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-P3ejLAuezi/a7DfLk6SaqGUcDIhM8tfeNbJ3fAu2sPXgOOpHLPkEKw9nJc8C365B+fsZVX0B5GYuDX4pXa3GMQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^12.0.0 || ^13.0.0",
|
||||||
|
"@angular/core": "^12.0.0 || ^13.0.0",
|
||||||
|
"rxjs": "^6.0.0 || ^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ng-packagr": {
|
"node_modules/ng-packagr": {
|
||||||
"version": "13.0.3",
|
"version": "13.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz",
|
||||||
|
@ -21901,6 +21915,14 @@
|
||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ng-dynamic-component": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ng-dynamic-component/-/ng-dynamic-component-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-P3ejLAuezi/a7DfLk6SaqGUcDIhM8tfeNbJ3fAu2sPXgOOpHLPkEKw9nJc8C365B+fsZVX0B5GYuDX4pXa3GMQ==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ng-packagr": {
|
"ng-packagr": {
|
||||||
"version": "13.0.3",
|
"version": "13.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz",
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"@angular/router": "13.0.0",
|
"@angular/router": "13.0.0",
|
||||||
"autolinker": "3.14.3",
|
"autolinker": "3.14.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
"ng-dynamic-component": "10.1.0",
|
||||||
"openvidu-browser": "2.21.0-beta1",
|
"openvidu-browser": "2.21.0-beta1",
|
||||||
"rxjs": "7.4.0",
|
"rxjs": "7.4.0",
|
||||||
"tslib": "2.3.1",
|
"tslib": "2.3.1",
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
"@angular/flex-layout": "^13.0.0-beta.36",
|
"@angular/flex-layout": "^13.0.0-beta.36",
|
||||||
"autolinker": "^3.14.3",
|
"autolinker": "^3.14.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"openvidu-browser": "^2.20.0"
|
"openvidu-browser": "^2.20.0",
|
||||||
|
"ng-dynamic-component": "^10.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
|
|
|
@ -1,35 +1,22 @@
|
||||||
<div id="layout" class="bounds">
|
<div id="layout" class="bounds">
|
||||||
<!-- Custom local participant -->
|
|
||||||
<ng-container *ngIf="customLocalParticipantTemplate; else defaultLocalParticipant">
|
|
||||||
<ng-container *ngTemplateOutlet="customLocalParticipantTemplate"></ng-container>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Default local participant if custom participant is not injected -->
|
|
||||||
<ng-template #defaultLocalParticipant>
|
|
||||||
<div
|
<div
|
||||||
class="OT_root OT_publisher"
|
class="OT_root OT_publisher"
|
||||||
id="localUser"
|
id="localUser"
|
||||||
*ngFor="let connection of localParticipant | connections"
|
*ngFor="let connection of localParticipant | connections"
|
||||||
[ngClass]="{ OV_small: !connection.streamManager?.stream?.videoActive }"
|
[ngClass]="{ OV_small: !connection.streamManager?.stream?.videoActive }"
|
||||||
>
|
>
|
||||||
<ov-stream [participant]="connection" [videoEnlarged]="connection.videoEnlarged"></ov-stream>
|
<ng-template #localStream [ngComponentOutlet]="_localStreamComponent" [ndcDynamicInputs]="{ participant: connection }">
|
||||||
</div>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Custom remote participant -->
|
|
||||||
<ng-container *ngIf="customRemoteParticipantsTemplate; else defaultRemoteParticipants">
|
|
||||||
<ng-container *ngTemplateOutlet="customRemoteParticipantsTemplate"></ng-container>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Default remote participants if custom participants is not injected -->
|
|
||||||
<ng-template #defaultRemoteParticipants>
|
|
||||||
<div
|
<div
|
||||||
*ngFor="let connection of remoteParticipants | connections"
|
*ngFor="let connection of remoteParticipants | connections"
|
||||||
class="OT_root OT_publisher"
|
class="OT_root OT_publisher"
|
||||||
id="remote-participant"
|
id="remote-participant"
|
||||||
[ngClass]="{ OV_small: !connection.streamManager?.stream?.videoActive }"
|
[ngClass]="{ OV_small: !connection.streamManager?.stream?.videoActive }"
|
||||||
>
|
>
|
||||||
<ov-stream [participant]="connection" [videoEnlarged]="connection.videoEnlarged"></ov-stream>
|
<!-- Dynamic ov-stream component injected -->
|
||||||
</div>
|
<ng-template #remoteStream [ngComponentOutlet]="_remoteStreamComponent" [ndcDynamicInputs]="{ participant: connection }">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { AfterViewInit, Component, ContentChild, OnDestroy, OnInit, TemplateRef } from '@angular/core';
|
import { AfterViewInit, Component, OnDestroy, OnInit, Type, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { ParticipantService } from '../../services/participant/participant.service';
|
import { ParticipantService } from '../../services/participant/participant.service';
|
||||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||||
import { LayoutService } from '../../services/layout/layout.service';
|
import { LayoutService } from '../../services/layout/layout.service';
|
||||||
|
import { LibraryComponents } from '../../config/lib.config';
|
||||||
|
import { LibraryConfigService } from '../../services/library-config/library-config.service';
|
||||||
|
import { StreamComponent } from '../stream/stream.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-layout',
|
selector: 'ov-layout',
|
||||||
|
@ -10,8 +13,10 @@ import { LayoutService } from '../../services/layout/layout.service';
|
||||||
styleUrls: ['./layout.component.css']
|
styleUrls: ['./layout.component.css']
|
||||||
})
|
})
|
||||||
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
@ContentChild('customLocalParticipant', { read: TemplateRef }) customLocalParticipantTemplate: TemplateRef<any>;
|
_localStream: ViewContainerRef;
|
||||||
@ContentChild('customRemoteParticipants', { read: TemplateRef }) customRemoteParticipantsTemplate: TemplateRef<any>;
|
_localStreamComponent: Type<any>;
|
||||||
|
_remoteStream: ViewContainerRef;
|
||||||
|
_remoteStreamComponent: Type<any>;
|
||||||
|
|
||||||
localParticipant: ParticipantAbstractModel;
|
localParticipant: ParticipantAbstractModel;
|
||||||
remoteParticipants: ParticipantAbstractModel[] = [];
|
remoteParticipants: ParticipantAbstractModel[] = [];
|
||||||
|
@ -19,10 +24,48 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
protected remoteParticipantsSubs: Subscription;
|
protected remoteParticipantsSubs: Subscription;
|
||||||
protected updateLayoutInterval: NodeJS.Timer;
|
protected updateLayoutInterval: NodeJS.Timer;
|
||||||
|
|
||||||
constructor(protected layoutService: LayoutService, protected participantService: ParticipantService) {}
|
constructor(
|
||||||
|
protected libraryConfigSrv: LibraryConfigService,
|
||||||
|
protected layoutService: LayoutService,
|
||||||
|
protected participantService: ParticipantService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@ViewChild('localStream', { static: false, read: ViewContainerRef })
|
||||||
|
set stream(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._localStream = reference;
|
||||||
|
|
||||||
|
if (this._localStream) {
|
||||||
|
let component = StreamComponent;
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.STREAM)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.STREAM);
|
||||||
|
}
|
||||||
|
// this._stream?.clear();
|
||||||
|
this._localStreamComponent = component;
|
||||||
|
// this._stream.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild('remoteStream', { static: false, read: ViewContainerRef })
|
||||||
|
set remoteStream(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._remoteStream = reference;
|
||||||
|
|
||||||
|
if (this._remoteStream) {
|
||||||
|
let component = StreamComponent;
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.STREAM)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.STREAM);
|
||||||
|
}
|
||||||
|
// this.remoteStream?.clear();
|
||||||
|
this._remoteStreamComponent = component;
|
||||||
|
// this._stream.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subscribeToUsers();
|
this.subscribeToParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {}
|
ngAfterViewInit() {}
|
||||||
|
@ -34,7 +77,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
if (this.remoteParticipantsSubs) this.remoteParticipantsSubs.unsubscribe();
|
if (this.remoteParticipantsSubs) this.remoteParticipantsSubs.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected subscribeToUsers() {
|
protected subscribeToParticipants() {
|
||||||
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
|
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
|
||||||
this.localParticipant = p;
|
this.localParticipant = p;
|
||||||
this.layoutService.update();
|
this.layoutService.update();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { ChatService } from '../../services/chat/chat.service';
|
import { ChatService } from '../../../services/chat/chat.service';
|
||||||
import { ChatServiceMock } from '../../services/chat/chat.service.mock';
|
import { ChatServiceMock } from '../../../services/chat/chat.service.mock';
|
||||||
|
|
||||||
import { ChatPanelComponent } from './chat-panel.component';
|
import { ChatPanelComponent } from './chat-panel.component';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { ChatMessage } from '../../models/chat.model';
|
import { ChatMessage } from '../../../models/chat.model';
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../../models/menu.model';
|
||||||
import { ChatService } from '../../services/chat/chat.service';
|
import { ChatService } from '../../../services/chat/chat.service';
|
||||||
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-chat-panel',
|
selector: 'ov-chat-panel',
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
<ng-container *ngIf="isChatPanelOpened" #chat></ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="isParticipantsPanelOpened" #participants></ng-container>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PanelComponent } from './panel.component';
|
||||||
|
|
||||||
|
describe('PanelComponent', () => {
|
||||||
|
let component: PanelComponent;
|
||||||
|
let fixture: ComponentFixture<PanelComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ PanelComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PanelComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
|
import { skip, Subscription } from 'rxjs';
|
||||||
|
import { LibraryComponents } from '../../config/lib.config';
|
||||||
|
import { MenuType } from '../../models/menu.model';
|
||||||
|
import { LibraryConfigService } from '../../services/library-config/library-config.service';
|
||||||
|
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
import { ChatPanelComponent } from './chat-panel/chat-panel.component';
|
||||||
|
import { ParticipantsPanelComponent } from './participants-panel/participants-panel/participants-panel.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ov-panel',
|
||||||
|
templateUrl: './panel.component.html',
|
||||||
|
styleUrls: ['./panel.component.css']
|
||||||
|
})
|
||||||
|
export class PanelComponent implements OnInit, OnDestroy {
|
||||||
|
isParticipantsPanelOpened: boolean;
|
||||||
|
isChatPanelOpened: boolean;
|
||||||
|
_chat: ViewContainerRef;
|
||||||
|
_participants: ViewContainerRef;
|
||||||
|
menuSubscription: Subscription;
|
||||||
|
|
||||||
|
@ViewChild('chat', { static: false, read: ViewContainerRef })
|
||||||
|
set chat(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._chat = reference;
|
||||||
|
|
||||||
|
if (this._chat) {
|
||||||
|
let component = ChatPanelComponent;
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.CHAT_PANEL)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.CHAT_PANEL);
|
||||||
|
}
|
||||||
|
this._chat?.clear();
|
||||||
|
this._chat.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild('participants', { static: false, read: ViewContainerRef })
|
||||||
|
set participants(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._participants = reference;
|
||||||
|
|
||||||
|
if (this._participants) {
|
||||||
|
let component = ParticipantsPanelComponent;
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.PARTICIPANTS_PANEL)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.PARTICIPANTS_PANEL);
|
||||||
|
}
|
||||||
|
this._participants?.clear();
|
||||||
|
this._participants.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(protected libraryConfigSrv: LibraryConfigService, protected menuService: SidenavMenuService) {}
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.isChatPanelOpened = false;
|
||||||
|
this.isParticipantsPanelOpened = false;
|
||||||
|
if (this.menuSubscription) this.menuSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||||
import { ParticipantAbstractModel, ParticipantModel } from '../../../models/participant.model';
|
import { ParticipantAbstractModel, ParticipantModel } from '../../../../models/participant.model';
|
||||||
import { ParticipantService } from '../../../services/participant/participant.service';
|
import { ParticipantService } from '../../../../services/participant/participant.service';
|
||||||
import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-participants-panel',
|
selector: 'ov-participants-panel',
|
|
@ -11,22 +11,30 @@
|
||||||
fixedBottomGap="0"
|
fixedBottomGap="0"
|
||||||
>
|
>
|
||||||
<!-- Custom menu content -->
|
<!-- Custom menu content -->
|
||||||
<ng-container *ngIf="customPanelContentTemplate; else defaultPanelContent">
|
<!-- <ng-container *ngIf="customPanelContentTemplate; else defaultPanelContent"> -->
|
||||||
<ng-container *ngTemplateOutlet="customPanelContentTemplate"></ng-container>
|
<!-- <ng-container *ngTemplateOutlet="customPanelContentTemplate"></ng-container> -->
|
||||||
</ng-container>
|
<!-- </ng-container> -->
|
||||||
|
|
||||||
<!-- Default menu content if custom menu content is not injected -->
|
<!-- Default menu content if custom menu content is not injected -->
|
||||||
<ng-template #defaultPanelContent>
|
<!-- <ng-template #defaultPanelContent>
|
||||||
<ov-chat-panel *ngIf="isChatPanelOpened"></ov-chat-panel>
|
<ov-chat-panel *ngIf="isChatPanelOpened"></ov-chat-panel>
|
||||||
<ov-participants-panel *ngIf="isParticipantsPanelOpened"></ov-participants-panel>
|
<ov-participants-panel *ngIf="isParticipantsPanelOpened"></ov-participants-panel>
|
||||||
</ng-template>
|
</ng-template> -->
|
||||||
|
<ng-template #panel></ng-template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
|
|
||||||
<!-- OPENVIDU LAYOUT -->
|
<!-- OPENVIDU LAYOUT -->
|
||||||
<mat-sidenav-content class="sidenav-main">
|
<mat-sidenav-content class="sidenav-main">
|
||||||
<div id="layout-container">
|
<!-- <div id="layout-container">
|
||||||
<ng-content select="[layout]"></ng-content>
|
<ng-content select="[layout]"></ng-content>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
<ng-template #layout></ng-template>
|
||||||
|
|
||||||
|
|
||||||
</mat-sidenav-content>
|
</mat-sidenav-content>
|
||||||
</mat-sidenav-container>
|
</mat-sidenav-container>
|
||||||
|
|
||||||
|
@ -37,9 +45,11 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-container> -->
|
</ng-container> -->
|
||||||
|
|
||||||
<ng-container *ngIf="toolbarTemplate">
|
<!-- <ng-container *ngIf="toolbarTemplate">
|
||||||
<div id="footer-container">
|
<div id="footer-container">
|
||||||
<ng-container *ngTemplateOutlet="toolbarTemplate"></ng-container>
|
<ng-container *ngTemplateOutlet="toolbarTemplate"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container> -->
|
||||||
|
|
||||||
|
<ng-template #toolbar></ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
import { Component, ContentChild, EventEmitter, HostListener, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
TemplateRef,
|
||||||
|
ViewChild,
|
||||||
|
ViewContainerRef
|
||||||
|
} from '@angular/core';
|
||||||
import { Subscriber, Session, StreamEvent, StreamPropertyChangedEvent, SessionDisconnectedEvent, ConnectionEvent } from 'openvidu-browser';
|
import { Subscriber, Session, StreamEvent, StreamPropertyChangedEvent, SessionDisconnectedEvent, ConnectionEvent } from 'openvidu-browser';
|
||||||
|
|
||||||
import { VideoType } from '../../models/video-type.model';
|
import { VideoType } from '../../models/video-type.model';
|
||||||
|
@ -8,7 +19,6 @@ import { ChatService } from '../../services/chat/chat.service';
|
||||||
import { LoggerService } from '../../services/logger/logger.service';
|
import { LoggerService } from '../../services/logger/logger.service';
|
||||||
import { WebrtcService } from '../../services/webrtc/webrtc.service';
|
import { WebrtcService } from '../../services/webrtc/webrtc.service';
|
||||||
import { TokenService } from '../../services/token/token.service';
|
import { TokenService } from '../../services/token/token.service';
|
||||||
import { PlatformService } from '../../services/platform/platform.service';
|
|
||||||
import { ActionService } from '../../services/action/action.service';
|
import { ActionService } from '../../services/action/action.service';
|
||||||
import { Signal } from '../../models/signal.model';
|
import { Signal } from '../../models/signal.model';
|
||||||
import { ParticipantService } from '../../services/participant/participant.service';
|
import { ParticipantService } from '../../services/participant/participant.service';
|
||||||
|
@ -18,6 +28,11 @@ import { LayoutService } from '../../services/layout/layout.service';
|
||||||
import { Subscription, skip } from 'rxjs';
|
import { Subscription, skip } from 'rxjs';
|
||||||
import { MenuType } from '../../models/menu.model';
|
import { MenuType } from '../../models/menu.model';
|
||||||
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.service';
|
||||||
|
import { ToolbarComponent } from '../toolbar/toolbar.component';
|
||||||
|
import { LibraryConfigService } from '../../services/library-config/library-config.service';
|
||||||
|
import { LayoutComponent } from '../layout/layout.component';
|
||||||
|
import { PanelComponent } from '../panel/panel.component';
|
||||||
|
import { LibraryComponents } from '../../config/lib.config';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-session',
|
selector: 'ov-session',
|
||||||
|
@ -25,14 +40,14 @@ import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.ser
|
||||||
styleUrls: ['./session.component.css']
|
styleUrls: ['./session.component.css']
|
||||||
})
|
})
|
||||||
export class SessionComponent implements OnInit {
|
export class SessionComponent implements OnInit {
|
||||||
@ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef<any>;
|
// @ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef<any>;
|
||||||
@ContentChild('customPanelContent', { read: TemplateRef }) customPanelContentTemplate: TemplateRef<any>;
|
@ContentChild('customPanelContent', { read: TemplateRef }) customPanelContentTemplate: TemplateRef<any>;
|
||||||
@ContentChild('customLayoutElement', { read: TemplateRef }) customLayoutElementTemplate: TemplateRef<any>;
|
@ContentChild('customLayoutElement', { read: TemplateRef }) customLayoutElementTemplate: TemplateRef<any>;
|
||||||
|
|
||||||
@Input() tokens: { webcam: string; screen: string };
|
@Input() tokens: { webcam: string; screen: string };
|
||||||
@Output() _session = new EventEmitter<any>();
|
// @Output() _session = new EventEmitter<any>();
|
||||||
@Output() _publisher = new EventEmitter<any>();
|
// @Output() _publisher = new EventEmitter<any>();
|
||||||
@Output() _error = new EventEmitter<any>();
|
// @Output() _error = new EventEmitter<any>();
|
||||||
|
|
||||||
session: Session;
|
session: Session;
|
||||||
sessionScreen: Session;
|
sessionScreen: Session;
|
||||||
|
@ -40,8 +55,7 @@ export class SessionComponent implements OnInit {
|
||||||
sideMenu: MatSidenav;
|
sideMenu: MatSidenav;
|
||||||
|
|
||||||
sidenavMode: SidenavMode = SidenavMode.SIDE;
|
sidenavMode: SidenavMode = SidenavMode.SIDE;
|
||||||
isParticipantsPanelOpened: boolean;
|
|
||||||
isChatPanelOpened: boolean;
|
|
||||||
protected readonly SIDENAV_WIDTH_LIMIT_MODE = 790;
|
protected readonly SIDENAV_WIDTH_LIMIT_MODE = 790;
|
||||||
|
|
||||||
protected menuSubscription: Subscription;
|
protected menuSubscription: Subscription;
|
||||||
|
@ -51,6 +65,10 @@ export class SessionComponent implements OnInit {
|
||||||
|
|
||||||
protected log: ILogger;
|
protected log: ILogger;
|
||||||
|
|
||||||
|
_toolbar: ViewContainerRef;
|
||||||
|
_layout: ViewContainerRef;
|
||||||
|
_panel: ViewContainerRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected actionService: ActionService,
|
protected actionService: ActionService,
|
||||||
protected webrtcService: WebrtcService,
|
protected webrtcService: WebrtcService,
|
||||||
|
@ -60,12 +78,63 @@ export class SessionComponent implements OnInit {
|
||||||
protected tokenService: TokenService,
|
protected tokenService: TokenService,
|
||||||
protected layoutService: LayoutService,
|
protected layoutService: LayoutService,
|
||||||
protected menuService: SidenavMenuService,
|
protected menuService: SidenavMenuService,
|
||||||
|
protected libraryConfigSrv: LibraryConfigService
|
||||||
protected platformService: PlatformService
|
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('SessionComponent');
|
this.log = this.loggerSrv.get('SessionComponent');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewChild('toolbar', { static: false, read: ViewContainerRef })
|
||||||
|
set toolbar(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._toolbar = reference;
|
||||||
|
|
||||||
|
if (this._toolbar) {
|
||||||
|
let component = ToolbarComponent;
|
||||||
|
// Inject the custom component if exists
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.TOOLBAR)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.TOOLBAR);
|
||||||
|
}
|
||||||
|
this._toolbar?.clear();
|
||||||
|
this._toolbar.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild('layout', { static: false, read: ViewContainerRef })
|
||||||
|
set layout(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._layout = reference;
|
||||||
|
|
||||||
|
if (this._layout) {
|
||||||
|
let component = LayoutComponent;
|
||||||
|
// Inject the custom component if exists
|
||||||
|
if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.LAYOUT)) {
|
||||||
|
component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.LAYOUT);
|
||||||
|
}
|
||||||
|
this._layout?.clear();
|
||||||
|
this._layout.createComponent(component);
|
||||||
|
this.layoutService.initialize();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild('panel', { static: false, read: ViewContainerRef })
|
||||||
|
set panel(reference: ViewContainerRef) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._panel = reference;
|
||||||
|
|
||||||
|
if (this._panel) {
|
||||||
|
let component = PanelComponent;
|
||||||
|
// Inject the custom component if exists
|
||||||
|
// if (this.libraryConfigSrv.isCustomComponentDefined(LibraryComponents.PANEL)) {
|
||||||
|
// component = this.libraryConfigSrv.getCustomComponent(LibraryComponents.PANEL);
|
||||||
|
// }
|
||||||
|
this._panel?.clear();
|
||||||
|
this._panel.createComponent(component);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
@HostListener('window:beforeunload')
|
@HostListener('window:beforeunload')
|
||||||
beforeunloadHandler() {
|
beforeunloadHandler() {
|
||||||
this.leaveSession();
|
this.leaveSession();
|
||||||
|
@ -87,8 +156,6 @@ export class SessionComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.layoutService.initialize();
|
|
||||||
|
|
||||||
if (this.webrtcService.getWebcamSession() === null) {
|
if (this.webrtcService.getWebcamSession() === null) {
|
||||||
this.webrtcService.initialize();
|
this.webrtcService.initialize();
|
||||||
await this.webrtcService.initDefaultPublisher(undefined);
|
await this.webrtcService.initDefaultPublisher(undefined);
|
||||||
|
@ -113,7 +180,7 @@ export class SessionComponent implements OnInit {
|
||||||
// this.webrtcService.publishVideo(this.localUserService.getMyCameraPublisher(), false);
|
// this.webrtcService.publishVideo(this.localUserService.getMyCameraPublisher(), false);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
this._session.emit(this.session);
|
// this._session.emit(this.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -124,8 +191,6 @@ export class SessionComponent implements OnInit {
|
||||||
this.session = null;
|
this.session = null;
|
||||||
this.sessionScreen = null;
|
this.sessionScreen = null;
|
||||||
this.layoutService.clear();
|
this.layoutService.clear();
|
||||||
this.isChatPanelOpened = false;
|
|
||||||
this.isParticipantsPanelOpened = false;
|
|
||||||
if (this.menuSubscription) this.menuSubscription.unsubscribe();
|
if (this.menuSubscription) this.menuSubscription.unsubscribe();
|
||||||
if (this.layoutWidthSubscription) this.layoutWidthSubscription.unsubscribe();
|
if (this.layoutWidthSubscription) this.layoutWidthSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@ -152,11 +217,7 @@ export class SessionComponent implements OnInit {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.menuSubscription = this.menuService.menuOpenedObs.pipe(skip(1)).subscribe((ev: { opened: boolean; type?: MenuType }) => {
|
this.menuSubscription = this.menuService.menuOpenedObs.pipe(skip(1)).subscribe((ev: { opened: boolean; type?: MenuType }) => {
|
||||||
if (this.sideMenu) {
|
this.sideMenu && ev.opened ? this.sideMenu.open() : this.sideMenu.close();
|
||||||
this.isChatPanelOpened = ev.opened && ev.type === MenuType.CHAT;
|
|
||||||
this.isParticipantsPanelOpened = ev.opened && ev.type === MenuType.PARTICIPANTS;
|
|
||||||
ev.opened ? this.sideMenu.open() : this.sideMenu.close();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +242,7 @@ export class SessionComponent implements OnInit {
|
||||||
await this.webrtcService.publish(this.participantService.getMyCameraPublisher());
|
await this.webrtcService.publish(this.participantService.getMyCameraPublisher());
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._error.emit({ error: error.error, messgae: error.message, code: error.code, status: error.status });
|
// this._error.emit({ error: error.error, messgae: error.message, code: error.code, status: error.status });
|
||||||
this.log.e('There was an error connecting to the session:', error.code, error.message);
|
this.log.e('There was an error connecting to the session:', error.code, error.message);
|
||||||
this.actionService.openDialog('There was an error connecting to the session:', error?.error || error?.message);
|
this.actionService.openDialog('There was an error connecting to the session:', error?.error || error?.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,16 +52,10 @@ export class StreamComponent implements OnInit {
|
||||||
// this.isFullscreenEnabled = !this.isFullscreenEnabled;
|
// this.isFullscreenEnabled = !this.isFullscreenEnabled;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Has been mandatory fullscreen Input because of Input user did not fire changing
|
|
||||||
// the fullscreen user property in publisherStartSpeaking event in SessionComponent
|
|
||||||
@Input()
|
|
||||||
set videoEnlarged(enlarged: boolean) {
|
|
||||||
this.checkVideoSizeBigIcon(enlarged);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set participant(participant: StreamModel) {
|
set participant(participant: StreamModel) {
|
||||||
this._participant = participant;
|
this._participant = participant;
|
||||||
|
this.checkVideoSizeBigIcon(this._participant.videoEnlarged);
|
||||||
this.nicknameFormControl = new FormControl(this._participant.nickname, [Validators.maxLength(25), Validators.required]);
|
this.nicknameFormControl = new FormControl(this._participant.nickname, [Validators.maxLength(25), Validators.required]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#toolbar {
|
#toolbar {
|
||||||
height: 100%;
|
/* height: 100%; */
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--ov-light-color);
|
color: var(--ov-light-color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
import { Component, ContentChild, EventEmitter, HostListener, OnDestroy, OnInit, Output, TemplateRef } from '@angular/core';
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
TemplateRef,
|
||||||
|
ViewChild
|
||||||
|
} from '@angular/core';
|
||||||
import { skip, Subscription } from 'rxjs';
|
import { skip, Subscription } from 'rxjs';
|
||||||
import { TokenService } from '../../services/token/token.service';
|
import { TokenService } from '../../services/token/token.service';
|
||||||
import { ChatService } from '../../services/chat/chat.service';
|
import { ChatService } from '../../services/chat/chat.service';
|
||||||
|
@ -103,11 +114,9 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
this.subscribeToUserMediaProperties();
|
this.subscribeToUserMediaProperties();
|
||||||
this.subscribeToReconnection();
|
this.subscribeToReconnection();
|
||||||
|
|
||||||
if(!this.libraryConfigSrv.isUsingProLibrary()){
|
|
||||||
this.subscribeToMenuToggling();
|
this.subscribeToMenuToggling();
|
||||||
this.subscribeToChatMessages();
|
this.subscribeToChatMessages();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
toggleMicrophone() {
|
toggleMicrophone() {
|
||||||
this.onMicClicked.emit();
|
this.onMicClicked.emit();
|
||||||
|
@ -268,7 +277,7 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
protected subscribeToMenuToggling() {
|
protected subscribeToMenuToggling() {
|
||||||
this.menuTogglingSubscription = this.menuService.menuOpenedObs.subscribe((ev: {opened: boolean, type?: MenuType}) => {
|
this.menuTogglingSubscription = this.menuService.menuOpenedObs.subscribe((ev: { opened: boolean; type?: MenuType }) => {
|
||||||
this.isChatOpened = ev.opened && ev.type === MenuType.CHAT;
|
this.isChatOpened = ev.opened && ev.type === MenuType.CHAT;
|
||||||
this.isParticipantsOpened = ev.opened && ev.type === MenuType.PARTICIPANTS;
|
this.isParticipantsOpened = ev.opened && ev.type === MenuType.PARTICIPANTS;
|
||||||
if (this.isChatOpened) {
|
if (this.isChatOpened) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div id="call-container">
|
<div id="call-container">
|
||||||
<div id="user-settings-container" *ngIf="!joinSessionClicked && !closeClicked">
|
<div id="user-settings-container" *ngIf="!joinSessionClicked && !closeClicked">
|
||||||
<ov-user-settings (onJoinClicked)="onJoinClicked()" (onCloseClicked)="onLeaveSessionClicked()"></ov-user-settings>
|
<ov-user-settings (onJoinClicked)="_onJoinClicked()" (onCloseClicked)="onLeaveSessionClicked()"></ov-user-settings>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="spinner" *ngIf="joinSessionClicked && !isSessionAlive && !error">
|
<div id="spinner" *ngIf="joinSessionClicked && !isSessionAlive && !error">
|
||||||
|
@ -10,21 +10,23 @@
|
||||||
|
|
||||||
<div id="spinner" *ngIf="joinSessionClicked && !isSessionAlive && error">
|
<div id="spinner" *ngIf="joinSessionClicked && !isSessionAlive && error">
|
||||||
<mat-icon class="error-icon">error</mat-icon>
|
<mat-icon class="error-icon">error</mat-icon>
|
||||||
<span>{{errorMessage}}</span>
|
<span>{{ errorMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="session-container" *ngIf="joinSessionClicked && isSessionAlive && !error">
|
<div id="session-container" *ngIf="joinSessionClicked && isSessionAlive && !error">
|
||||||
<ov-session [tokens]="_tokens">
|
<ov-session [tokens]="_tokens">
|
||||||
<ng-template #toolbar>
|
|
||||||
|
<!-- Default toolbar -->
|
||||||
|
<!--<ng-template #toolbar toolbar>
|
||||||
<ov-toolbar
|
<ov-toolbar
|
||||||
(onCamClicked)="onCamClicked()"
|
(onCamClicked)="onCamClicked()"
|
||||||
(onMicClicked)="onMicClicked()"
|
(onMicClicked)="onMicClicked()"
|
||||||
(onScreenShareClicked)="onScreenShareClicked()"
|
(onScreenShareClicked)="onScreenShareClicked()"
|
||||||
(onSpeakerLayoutClicked)="onSpeakerLayoutClicked()"
|
|
||||||
(onLeaveSessionClicked)="onLeaveSessionClicked()"
|
(onLeaveSessionClicked)="onLeaveSessionClicked()"
|
||||||
></ov-toolbar>
|
></ov-toolbar>
|
||||||
</ng-template>
|
</ng-template>-->
|
||||||
<ov-layout layout></ov-layout>
|
|
||||||
|
<!-- <ov-layout layout></ov-layout> -->
|
||||||
</ov-session>
|
</ov-session>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,17 +1,31 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import {
|
||||||
import { RestService } from '../../services/rest/rest.service';
|
Component,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ViewChild,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
AfterViewInit,
|
||||||
|
ViewContainerRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import { LibraryConfigService } from '../../services/library-config/library-config.service';
|
||||||
|
import { ToolbarComponent } from '../toolbar/toolbar.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-videoconference',
|
selector: 'ov-videoconference',
|
||||||
templateUrl: './videoconference.component.html',
|
templateUrl: './videoconference.component.html',
|
||||||
styleUrls: ['./videoconference.component.css']
|
styleUrls: ['./videoconference.component.css']
|
||||||
})
|
})
|
||||||
export class VideoconferenceComponent implements OnInit {
|
export class VideoconferenceComponent implements OnInit, AfterViewInit {
|
||||||
@Input() sessionName: string;
|
@Input() sessionName: string;
|
||||||
@Input() userName: string;
|
@Input() userName: string;
|
||||||
@Input() openviduServerUrl: string;
|
@Input() openviduServerUrl: string;
|
||||||
@Input() openviduSecret: string;
|
@Input() openviduSecret: string;
|
||||||
@Input() tokens: { webcam: string; screen: string };
|
// @Input() tokens: { webcam: string; screen: string };
|
||||||
|
|
||||||
|
@Output() onJoinClicked = new EventEmitter<any>();
|
||||||
|
@Output() onCloseClicked = new EventEmitter<any>();
|
||||||
|
|
||||||
joinSessionClicked: boolean = false;
|
joinSessionClicked: boolean = false;
|
||||||
closeClicked: boolean = false;
|
closeClicked: boolean = false;
|
||||||
|
@ -20,42 +34,91 @@ export class VideoconferenceComponent implements OnInit {
|
||||||
error: boolean = false;
|
error: boolean = false;
|
||||||
errorMessage: string = '';
|
errorMessage: string = '';
|
||||||
|
|
||||||
constructor(private restService: RestService) {}
|
_toolbar: ViewContainerRef;
|
||||||
|
|
||||||
ngOnInit() {}
|
constructor(protected libraryConfigSrv: LibraryConfigService, private cd: ChangeDetectorRef) {}
|
||||||
|
|
||||||
async onJoinClicked() {
|
// @ViewChild('toolbar', { static: false, read: ViewContainerRef })
|
||||||
if (!this.tokens || (!this.tokens?.webcam && !this.tokens?.screen)) {
|
// set toolbar(reference: ViewContainerRef) {
|
||||||
//No tokens received
|
// setTimeout(() => {
|
||||||
|
// console.log('setting ref', reference);
|
||||||
|
// this._toolbar = reference;
|
||||||
|
|
||||||
if (!!this.sessionName && !!this.openviduServerUrl && !!this.openviduSecret) {
|
// if (this._toolbar) {
|
||||||
// Generate tokens
|
// let component = ToolbarComponent;
|
||||||
this._tokens = {
|
// if (this.libraryConfigSrv.isCustomComponentDefined('ov-toolbar')) {
|
||||||
webcam: await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret),
|
// component = this.libraryConfigSrv.getToolbarComponent();
|
||||||
screen: await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret)
|
// }
|
||||||
};
|
// this._toolbar?.clear();
|
||||||
} else {
|
// this._toolbar.createComponent(component);
|
||||||
// No tokens received and can't generate them
|
// }
|
||||||
this.error = true;
|
// }, 100);
|
||||||
this.errorMessage = `Cannot access to OpenVidu Server with url '${this.openviduServerUrl}' to genere tokens for session '${this.sessionName}'`;
|
// }
|
||||||
throw this.errorMessage;
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
// if(this.customToolbar && this.libraryConfigSrv.isCustomComponentDefined('ov-toolbar')){
|
||||||
|
// const viewContainerRef = this.customToolbar.viewContainerRef;
|
||||||
|
// viewContainerRef.clear();
|
||||||
|
// const componentRef = viewContainerRef.createComponent<any>(this.libraryConfigSrv.getToolbarComponent());
|
||||||
|
// } else {
|
||||||
|
// this.customToolbar.viewContainerRef.clear();
|
||||||
|
// const viewContainerRef = this.toolbar.viewContainerRef;
|
||||||
|
// viewContainerRef.clear();
|
||||||
|
// viewContainerRef.createComponent<any>(ToolbarComponent);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
} else if (!this.tokens?.webcam || !this.tokens?.screen) {
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input('tokens')
|
||||||
|
set tokens(tokens: { webcam: string; screen: string }) {
|
||||||
|
if (!!tokens?.webcam || !!this.tokens?.screen) {
|
||||||
// 1 token received
|
// 1 token received
|
||||||
const aditionalToken = await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret);
|
this.cd.detectChanges();
|
||||||
this._tokens = {
|
// this.cd.markForCheck();
|
||||||
webcam: !!this.tokens.webcam ? this.tokens.webcam : aditionalToken,
|
this._tokens = tokens;
|
||||||
screen: !!this.tokens.screen ? this.tokens.screen : aditionalToken
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// 2 tokens received.
|
|
||||||
this._tokens = {
|
|
||||||
webcam: this.tokens.webcam,
|
|
||||||
screen: this.tokens.screen
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.joinSessionClicked = true;
|
this.joinSessionClicked = true;
|
||||||
this.isSessionAlive = true;
|
this.isSessionAlive = true;
|
||||||
|
} else {
|
||||||
|
//No tokens received
|
||||||
|
throw new Error('No tokens received');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onJoinClicked() {
|
||||||
|
this.onJoinClicked.emit();
|
||||||
|
// if (!this.tokens || (!this.tokens?.webcam && !this.tokens?.screen)) {
|
||||||
|
// //No tokens received
|
||||||
|
|
||||||
|
// if (!!this.sessionName && !!this.openviduServerUrl && !!this.openviduSecret) {
|
||||||
|
// // Generate tokens
|
||||||
|
// this._tokens = {
|
||||||
|
// webcam: await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret),
|
||||||
|
// screen: await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret)
|
||||||
|
// };
|
||||||
|
// } else {
|
||||||
|
// // No tokens received and can't generate them
|
||||||
|
// this.error = true;
|
||||||
|
// this.errorMessage = `Cannot access to OpenVidu Server with url '${this.openviduServerUrl}' to genere tokens for session '${this.sessionName}'`;
|
||||||
|
// throw this.errorMessage;
|
||||||
|
// }
|
||||||
|
// } else if (!this.tokens?.webcam || !this.tokens?.screen) {
|
||||||
|
// // 1 token received
|
||||||
|
// const aditionalToken = await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret);
|
||||||
|
// this._tokens = {
|
||||||
|
// webcam: !!this.tokens.webcam ? this.tokens.webcam : aditionalToken,
|
||||||
|
// screen: !!this.tokens.screen ? this.tokens.screen : aditionalToken
|
||||||
|
// };
|
||||||
|
// } else {
|
||||||
|
// // 2 tokens received.
|
||||||
|
// this._tokens = {
|
||||||
|
// webcam: this.tokens.webcam,
|
||||||
|
// screen: this.tokens.screen
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// this.joinSessionClicked = true;
|
||||||
|
// this.isSessionAlive = true;
|
||||||
}
|
}
|
||||||
onLeaveSessionClicked() {
|
onLeaveSessionClicked() {
|
||||||
this.isSessionAlive = false;
|
this.isSessionAlive = false;
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
|
import { Type } from '@angular/core';
|
||||||
|
|
||||||
export interface LibConfig {
|
export interface LibConfig {
|
||||||
environment: {
|
environment: {
|
||||||
production: boolean;
|
production: boolean;
|
||||||
useProdLibrary?: boolean
|
useProdLibrary?: boolean;
|
||||||
|
customComponents?: { LibraryComponents: Type<any> };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum LibraryComponents {
|
||||||
|
TOOLBAR = 'ov-toolbar',
|
||||||
|
LAYOUT = 'ov-layout',
|
||||||
|
PANEL = 'ov-panel',
|
||||||
|
CHAT_PANEL = 'ov-chat-panel',
|
||||||
|
PARTICIPANTS_PANEL = 'ov-participants-panel',
|
||||||
|
STREAM = "ov-stream"
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import { HttpClientModule } from '@angular/common/http';
|
||||||
import { UserSettingsComponent } from './components/user-settings/user-settings.component';
|
import { UserSettingsComponent } from './components/user-settings/user-settings.component';
|
||||||
import { ToolbarComponent } from './components/toolbar/toolbar.component';
|
import { ToolbarComponent } from './components/toolbar/toolbar.component';
|
||||||
import { VideoComponent } from './components/video/video.component';
|
import { VideoComponent } from './components/video/video.component';
|
||||||
import { ChatPanelComponent } from './components/chat-panel/chat-panel.component';
|
import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component';
|
||||||
import { SessionComponent } from './components/session/session.component';
|
import { SessionComponent } from './components/session/session.component';
|
||||||
import { LayoutComponent } from './components/layout/layout.component';
|
import { LayoutComponent } from './components/layout/layout.component';
|
||||||
import { StreamComponent } from './components/stream/stream.component';
|
import { StreamComponent } from './components/stream/stream.component';
|
||||||
|
@ -54,9 +54,14 @@ import { DocumentService } from './services/document/document.service';
|
||||||
import { LayoutService } from './services/layout/layout.service';
|
import { LayoutService } from './services/layout/layout.service';
|
||||||
import { SidenavMenuService } from './services/sidenav-menu/sidenav-menu.service';
|
import { SidenavMenuService } from './services/sidenav-menu/sidenav-menu.service';
|
||||||
import { ParticipantService } from './services/participant/participant.service';
|
import { ParticipantService } from './services/participant/participant.service';
|
||||||
import { ParticipantItemComponent } from './components/participants-panel/participant-item/participant-item.component';
|
import { ParticipantItemComponent } from './components/panel/participants-panel/participant-item/participant-item.component';
|
||||||
import { ParticipantsPanelComponent } from './components/participants-panel/participants-panel/participants-panel.component';
|
import { ParticipantsPanelComponent } from './components/panel/participants-panel/participants-panel/participants-panel.component';
|
||||||
import { VideoconferenceComponent } from './components/videoconference/videoconference.component';
|
import { VideoconferenceComponent } from './components/videoconference/videoconference.component';
|
||||||
|
import { PanelComponent } from './components/panel/panel.component';
|
||||||
|
|
||||||
|
// Used for loading dynamic components because of Inputs and Outputs are not supported in the official Angular way
|
||||||
|
// https://github.com/angular/angular/issues/15360
|
||||||
|
import { DynamicIoModule } from 'ng-dynamic-component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -75,7 +80,8 @@ import { VideoconferenceComponent } from './components/videoconference/videoconf
|
||||||
NicknamePipe,
|
NicknamePipe,
|
||||||
ParticipantItemComponent,
|
ParticipantItemComponent,
|
||||||
ParticipantsPanelComponent,
|
ParticipantsPanelComponent,
|
||||||
VideoconferenceComponent
|
VideoconferenceComponent,
|
||||||
|
PanelComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -102,7 +108,8 @@ import { VideoconferenceComponent } from './components/videoconference/videoconf
|
||||||
FlexLayoutModule,
|
FlexLayoutModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatDividerModule,
|
MatDividerModule,
|
||||||
MatListModule
|
MatListModule,
|
||||||
|
DynamicIoModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
ActionService,
|
ActionService,
|
||||||
|
|
|
@ -5,12 +5,12 @@ import { LibConfig } from '../../config/lib.config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LibraryConfigService {
|
export class LibraryConfigService {
|
||||||
|
|
||||||
private configuration: LibConfig;
|
private configuration: LibConfig;
|
||||||
|
|
||||||
constructor(@Inject('LIB_CONFIG') config: LibConfig) {
|
constructor(@Inject('LIB_CONFIG') config: LibConfig) {
|
||||||
this.configuration = config;
|
this.configuration = config;
|
||||||
console.log(this.configuration);
|
console.log(this.configuration);
|
||||||
this.isUsingProLibrary() ? console.log('Using PRO library') : console.log('Using CE library');
|
|
||||||
if(this.isProduction()) console.log('Production Mode');
|
if(this.isProduction()) console.log('Production Mode');
|
||||||
// console.log(version)
|
// console.log(version)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,11 @@ export class LibraryConfigService {
|
||||||
return this.configuration?.environment?.production;
|
return this.configuration?.environment?.production;
|
||||||
}
|
}
|
||||||
|
|
||||||
isUsingProLibrary(): boolean {
|
isCustomComponentDefined(component: string): boolean {
|
||||||
return !!this.configuration?.environment?.useProdLibrary;
|
return !!this.configuration?.environment?.customComponents && !!this.configuration.environment.customComponents[component];
|
||||||
|
}
|
||||||
|
|
||||||
|
getCustomComponent(component: string){
|
||||||
|
return this.configuration.environment.customComponents[component];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ export * from './lib/services/storage/storage.service';
|
||||||
export * from './lib/components/videoconference/videoconference.component';
|
export * from './lib/components/videoconference/videoconference.component';
|
||||||
export * from './lib/components/user-settings/user-settings.component';
|
export * from './lib/components/user-settings/user-settings.component';
|
||||||
export * from './lib/components/toolbar/toolbar.component';
|
export * from './lib/components/toolbar/toolbar.component';
|
||||||
export * from './lib/components/chat-panel/chat-panel.component';
|
export * from './lib/components/panel/chat-panel/chat-panel.component';
|
||||||
export * from './lib/components/participants-panel/participants-panel/participants-panel.component';
|
export * from './lib/components/panel/participants-panel/participants-panel/participants-panel.component';
|
||||||
export * from './lib/components/session/session.component';
|
export * from './lib/components/session/session.component';
|
||||||
export * from './lib/components/layout/layout.component';
|
export * from './lib/components/layout/layout.component';
|
||||||
export * from './lib/components/stream/stream.component';
|
export * from './lib/components/stream/stream.component';
|
||||||
|
|
Loading…
Reference in New Issue