diff --git a/openvidu-components-angular/package-lock.json b/openvidu-components-angular/package-lock.json index aaeb7aa4..f2a7f0b7 100644 --- a/openvidu-components-angular/package-lock.json +++ b/openvidu-components-angular/package-lock.json @@ -20,6 +20,7 @@ "@angular/router": "13.0.0", "autolinker": "3.14.3", "buffer": "^6.0.3", + "ng-dynamic-component": "^10.1.0", "openvidu-browser": "2.21.0-beta1", "rxjs": "7.4.0", "tslib": "2.3.1", @@ -9065,6 +9066,19 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "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": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz", @@ -21901,6 +21915,14 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "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": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-13.0.3.tgz", diff --git a/openvidu-components-angular/package.json b/openvidu-components-angular/package.json index 7576d7b0..02c8207b 100644 --- a/openvidu-components-angular/package.json +++ b/openvidu-components-angular/package.json @@ -27,6 +27,7 @@ "@angular/router": "13.0.0", "autolinker": "3.14.3", "buffer": "^6.0.3", + "ng-dynamic-component": "10.1.0", "openvidu-browser": "2.21.0-beta1", "rxjs": "7.4.0", "tslib": "2.3.1", diff --git a/openvidu-components-angular/projects/openvidu-angular/package.json b/openvidu-components-angular/projects/openvidu-angular/package.json index 1b2ff923..e4fb25f2 100644 --- a/openvidu-components-angular/projects/openvidu-angular/package.json +++ b/openvidu-components-angular/projects/openvidu-angular/package.json @@ -10,7 +10,8 @@ "@angular/flex-layout": "^13.0.0-beta.36", "autolinker": "^3.14.3", "buffer": "^6.0.3", - "openvidu-browser": "^2.20.0" + "openvidu-browser": "^2.20.0", + "ng-dynamic-component": "^10.1.0" }, "dependencies": { "tslib": "^2.3.0" diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html index db8e1767..3ac34cdd 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html @@ -1,35 +1,22 @@
- - - - +
+ + +
- - -
- -
-
- - - - - - - - -
- -
-
+
+ + + +
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts index 86815573..c27ed0b6 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts @@ -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 { ParticipantService } from '../../services/participant/participant.service'; import { ParticipantAbstractModel } from '../../models/participant.model'; 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({ selector: 'ov-layout', @@ -10,8 +13,10 @@ import { LayoutService } from '../../services/layout/layout.service'; styleUrls: ['./layout.component.css'] }) export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { - @ContentChild('customLocalParticipant', { read: TemplateRef }) customLocalParticipantTemplate: TemplateRef; - @ContentChild('customRemoteParticipants', { read: TemplateRef }) customRemoteParticipantsTemplate: TemplateRef; + _localStream: ViewContainerRef; + _localStreamComponent: Type; + _remoteStream: ViewContainerRef; + _remoteStreamComponent: Type; localParticipant: ParticipantAbstractModel; remoteParticipants: ParticipantAbstractModel[] = []; @@ -19,10 +24,48 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { protected remoteParticipantsSubs: Subscription; 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 { - this.subscribeToUsers(); + this.subscribeToParticipants(); } ngAfterViewInit() {} @@ -34,7 +77,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { if (this.remoteParticipantsSubs) this.remoteParticipantsSubs.unsubscribe(); } - protected subscribeToUsers() { + protected subscribeToParticipants() { this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => { this.localParticipant = p; this.layoutService.update(); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.css similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.css rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.css diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.html similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.html rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.html diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.spec.ts similarity index 82% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.spec.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.spec.ts index 8cc7ff68..0204558a 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.spec.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ChatService } from '../../services/chat/chat.service'; -import { ChatServiceMock } from '../../services/chat/chat.service.mock'; +import { ChatService } from '../../../services/chat/chat.service'; +import { ChatServiceMock } from '../../../services/chat/chat.service.mock'; import { ChatPanelComponent } from './chat-panel.component'; diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts similarity index 87% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts index 4182525d..a885dce2 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/chat-panel/chat-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts @@ -1,9 +1,9 @@ import { AfterViewInit, 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'; +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'; @Component({ selector: 'ov-chat-panel', diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.css new file mode 100644 index 00000000..e69de29b diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.html new file mode 100644 index 00000000..4d33588b --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.spec.ts new file mode 100644 index 00000000..b0f6a9d7 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PanelComponent } from './panel.component'; + +describe('PanelComponent', () => { + let component: PanelComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PanelComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.ts new file mode 100644 index 00000000..af3393f6 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/panel.component.ts @@ -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(); + } +} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.css similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.css rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.css diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.html similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.html rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.html diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.spec.ts similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.spec.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.spec.ts diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.ts similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participant-item/participant-item.component.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participant-item/participant-item.component.ts diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.css similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.css rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.css diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.html similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.html rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.html diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.spec.ts similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.spec.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.spec.ts diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.ts similarity index 83% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.ts rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.ts index 07496acb..a84faf49 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/participants-panel/participants-panel/participants-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/participants-panel/participants-panel/participants-panel.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; -import { ParticipantAbstractModel, ParticipantModel } from '../../../models/participant.model'; -import { ParticipantService } from '../../../services/participant/participant.service'; -import { SidenavMenuService } from '../../../services/sidenav-menu/sidenav-menu.service'; +import { ParticipantAbstractModel, ParticipantModel } from '../../../../models/participant.model'; +import { ParticipantService } from '../../../../services/participant/participant.service'; +import { SidenavMenuService } from '../../../../services/sidenav-menu/sidenav-menu.service'; @Component({ selector: 'ov-participants-panel', diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.html index 85367ff7..d27b1a43 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.html @@ -11,22 +11,30 @@ fixedBottomGap="0" > - - - + + + - + + + + + -
+ + + + + @@ -37,9 +45,11 @@
--> - + + + diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts index 8aa833f4..aced0154 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts @@ -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 { 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 { WebrtcService } from '../../services/webrtc/webrtc.service'; import { TokenService } from '../../services/token/token.service'; -import { PlatformService } from '../../services/platform/platform.service'; import { ActionService } from '../../services/action/action.service'; import { Signal } from '../../models/signal.model'; import { ParticipantService } from '../../services/participant/participant.service'; @@ -18,6 +28,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 { 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({ selector: 'ov-session', @@ -25,14 +40,14 @@ import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.ser styleUrls: ['./session.component.css'] }) export class SessionComponent implements OnInit { - @ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef; + // @ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef; @ContentChild('customPanelContent', { read: TemplateRef }) customPanelContentTemplate: TemplateRef; @ContentChild('customLayoutElement', { read: TemplateRef }) customLayoutElementTemplate: TemplateRef; @Input() tokens: { webcam: string; screen: string }; - @Output() _session = new EventEmitter(); - @Output() _publisher = new EventEmitter(); - @Output() _error = new EventEmitter(); + // @Output() _session = new EventEmitter(); + // @Output() _publisher = new EventEmitter(); + // @Output() _error = new EventEmitter(); session: Session; sessionScreen: Session; @@ -40,8 +55,7 @@ export class SessionComponent implements OnInit { sideMenu: MatSidenav; sidenavMode: SidenavMode = SidenavMode.SIDE; - isParticipantsPanelOpened: boolean; - isChatPanelOpened: boolean; + protected readonly SIDENAV_WIDTH_LIMIT_MODE = 790; protected menuSubscription: Subscription; @@ -51,6 +65,10 @@ export class SessionComponent implements OnInit { protected log: ILogger; + _toolbar: ViewContainerRef; + _layout: ViewContainerRef; + _panel: ViewContainerRef; + constructor( protected actionService: ActionService, protected webrtcService: WebrtcService, @@ -60,12 +78,63 @@ export class SessionComponent implements OnInit { protected tokenService: TokenService, protected layoutService: LayoutService, protected menuService: SidenavMenuService, - - protected platformService: PlatformService + protected libraryConfigSrv: LibraryConfigService ) { 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') beforeunloadHandler() { this.leaveSession(); @@ -87,8 +156,6 @@ export class SessionComponent implements OnInit { } async ngOnInit() { - this.layoutService.initialize(); - if (this.webrtcService.getWebcamSession() === null) { this.webrtcService.initialize(); await this.webrtcService.initDefaultPublisher(undefined); @@ -113,7 +180,7 @@ export class SessionComponent implements OnInit { // this.webrtcService.publishVideo(this.localUserService.getMyCameraPublisher(), false); // } - this._session.emit(this.session); + // this._session.emit(this.session); } ngOnDestroy() { @@ -124,8 +191,6 @@ export class SessionComponent implements OnInit { this.session = null; this.sessionScreen = null; this.layoutService.clear(); - this.isChatPanelOpened = false; - this.isParticipantsPanelOpened = false; if (this.menuSubscription) this.menuSubscription.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 }) => { - if (this.sideMenu) { - this.isChatPanelOpened = ev.opened && ev.type === MenuType.CHAT; - this.isParticipantsPanelOpened = ev.opened && ev.type === MenuType.PARTICIPANTS; - ev.opened ? this.sideMenu.open() : this.sideMenu.close(); - } + this.sideMenu && ev.opened ? this.sideMenu.open() : this.sideMenu.close(); }); } @@ -181,7 +242,7 @@ export class SessionComponent implements OnInit { await this.webrtcService.publish(this.participantService.getMyCameraPublisher()); } } 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.actionService.openDialog('There was an error connecting to the session:', error?.error || error?.message); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/stream/stream.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/stream/stream.component.ts index 1e4dac9f..1cfa1afe 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/stream/stream.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/stream/stream.component.ts @@ -52,16 +52,10 @@ export class StreamComponent implements OnInit { // 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() set participant(participant: StreamModel) { this._participant = participant; + this.checkVideoSizeBigIcon(this._participant.videoEnlarged); this.nicknameFormControl = new FormControl(this._participant.nickname, [Validators.maxLength(25), Validators.required]); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.css index 4c7809f9..60df9c8b 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.css +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.css @@ -1,5 +1,5 @@ #toolbar { - height: 100%; + /* height: 100%; */ background-color: transparent; color: var(--ov-light-color); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts index 6d8d0372..52502895 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts @@ -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 { TokenService } from '../../services/token/token.service'; import { ChatService } from '../../services/chat/chat.service'; @@ -103,10 +114,8 @@ export class ToolbarComponent implements OnInit, OnDestroy { this.subscribeToUserMediaProperties(); this.subscribeToReconnection(); - if(!this.libraryConfigSrv.isUsingProLibrary()){ - this.subscribeToMenuToggling(); - this.subscribeToChatMessages(); - } + this.subscribeToMenuToggling(); + this.subscribeToChatMessages(); } toggleMicrophone() { @@ -268,7 +277,7 @@ export class ToolbarComponent implements OnInit, OnDestroy { }); } 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.isParticipantsOpened = ev.opened && ev.type === MenuType.PARTICIPANTS; if (this.isChatOpened) { diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html index 20e6bc43..655bfc34 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html @@ -1,6 +1,6 @@
- +
@@ -10,21 +10,23 @@
error - {{errorMessage}} + {{ errorMessage }}
- - + + +
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts index f51d6949..ec918c9c 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts @@ -1,17 +1,31 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { RestService } from '../../services/rest/rest.service'; +import { + 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({ selector: 'ov-videoconference', templateUrl: './videoconference.component.html', styleUrls: ['./videoconference.component.css'] }) -export class VideoconferenceComponent implements OnInit { +export class VideoconferenceComponent implements OnInit, AfterViewInit { @Input() sessionName: string; @Input() userName: string; @Input() openviduServerUrl: string; @Input() openviduSecret: string; - @Input() tokens: { webcam: string; screen: string }; + // @Input() tokens: { webcam: string; screen: string }; + + @Output() onJoinClicked = new EventEmitter(); + @Output() onCloseClicked = new EventEmitter(); joinSessionClicked: boolean = false; closeClicked: boolean = false; @@ -20,42 +34,91 @@ export class VideoconferenceComponent implements OnInit { error: boolean = false; errorMessage: string = ''; - constructor(private restService: RestService) {} + _toolbar: ViewContainerRef; - ngOnInit() {} + constructor(protected libraryConfigSrv: LibraryConfigService, private cd: ChangeDetectorRef) {} - async onJoinClicked() { - if (!this.tokens || (!this.tokens?.webcam && !this.tokens?.screen)) { - //No tokens received + // @ViewChild('toolbar', { static: false, read: ViewContainerRef }) + // set toolbar(reference: ViewContainerRef) { + // setTimeout(() => { + // console.log('setting ref', reference); + // this._toolbar = reference; - 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) { + // if (this._toolbar) { + // let component = ToolbarComponent; + // if (this.libraryConfigSrv.isCustomComponentDefined('ov-toolbar')) { + // component = this.libraryConfigSrv.getToolbarComponent(); + // } + // this._toolbar?.clear(); + // this._toolbar.createComponent(component); + // } + // }, 100); + // } + + ngAfterViewInit() { + // if(this.customToolbar && this.libraryConfigSrv.isCustomComponentDefined('ov-toolbar')){ + // const viewContainerRef = this.customToolbar.viewContainerRef; + // viewContainerRef.clear(); + // const componentRef = viewContainerRef.createComponent(this.libraryConfigSrv.getToolbarComponent()); + // } else { + // this.customToolbar.viewContainerRef.clear(); + // const viewContainerRef = this.toolbar.viewContainerRef; + // viewContainerRef.clear(); + // viewContainerRef.createComponent(ToolbarComponent); + // } + } + + ngOnInit() { + } + + @Input('tokens') + set tokens(tokens: { webcam: string; screen: string }) { + if (!!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 - }; + this.cd.detectChanges(); + // this.cd.markForCheck(); + this._tokens = tokens; + this.joinSessionClicked = true; + this.isSessionAlive = true; } else { - // 2 tokens received. - this._tokens = { - webcam: this.tokens.webcam, - screen: this.tokens.screen - }; + //No tokens received + throw new Error('No tokens received'); } - this.joinSessionClicked = true; - this.isSessionAlive = true; + } + + 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() { this.isSessionAlive = false; diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/config/lib.config.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/config/lib.config.ts index 5c9f3fdc..084f1b8d 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/config/lib.config.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/config/lib.config.ts @@ -1,6 +1,19 @@ +import { Type } from '@angular/core'; + export interface LibConfig { environment: { production: boolean; - useProdLibrary?: boolean + useProdLibrary?: boolean; + customComponents?: { LibraryComponents: Type }; }; } + + +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" +} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts index 6885fe47..4cfb4445 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts @@ -29,7 +29,7 @@ import { HttpClientModule } from '@angular/common/http'; import { UserSettingsComponent } from './components/user-settings/user-settings.component'; import { ToolbarComponent } from './components/toolbar/toolbar.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 { LayoutComponent } from './components/layout/layout.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 { SidenavMenuService } from './services/sidenav-menu/sidenav-menu.service'; import { ParticipantService } from './services/participant/participant.service'; -import { ParticipantItemComponent } from './components/participants-panel/participant-item/participant-item.component'; -import { ParticipantsPanelComponent } from './components/participants-panel/participants-panel/participants-panel.component'; +import { ParticipantItemComponent } from './components/panel/participants-panel/participant-item/participant-item.component'; +import { ParticipantsPanelComponent } from './components/panel/participants-panel/participants-panel/participants-panel.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({ declarations: [ @@ -75,7 +80,8 @@ import { VideoconferenceComponent } from './components/videoconference/videoconf NicknamePipe, ParticipantItemComponent, ParticipantsPanelComponent, - VideoconferenceComponent + VideoconferenceComponent, + PanelComponent, ], imports: [ CommonModule, @@ -102,7 +108,8 @@ import { VideoconferenceComponent } from './components/videoconference/videoconf FlexLayoutModule, MatMenuModule, MatDividerModule, - MatListModule + MatListModule, + DynamicIoModule ], providers: [ ActionService, diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/library-config/library-config.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/library-config/library-config.service.ts index 51c28a4b..d6b81fae 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/library-config/library-config.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/library-config/library-config.service.ts @@ -5,12 +5,12 @@ import { LibConfig } from '../../config/lib.config'; @Injectable() export class LibraryConfigService { + private configuration: LibConfig; constructor(@Inject('LIB_CONFIG') config: LibConfig) { this.configuration = config; console.log(this.configuration); - this.isUsingProLibrary() ? console.log('Using PRO library') : console.log('Using CE library'); if(this.isProduction()) console.log('Production Mode'); // console.log(version) } @@ -22,7 +22,11 @@ export class LibraryConfigService { return this.configuration?.environment?.production; } - isUsingProLibrary(): boolean { - return !!this.configuration?.environment?.useProdLibrary; + isCustomComponentDefined(component: string): boolean { + return !!this.configuration?.environment?.customComponents && !!this.configuration.environment.customComponents[component]; + } + + getCustomComponent(component: string){ + return this.configuration.environment.customComponents[component]; } } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts index 143daa78..d7fef6a0 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts @@ -24,8 +24,8 @@ export * from './lib/services/storage/storage.service'; export * from './lib/components/videoconference/videoconference.component'; export * from './lib/components/user-settings/user-settings.component'; export * from './lib/components/toolbar/toolbar.component'; -export * from './lib/components/chat-panel/chat-panel.component'; -export * from './lib/components/participants-panel/participants-panel/participants-panel.component'; +export * from './lib/components/panel/chat-panel/chat-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/layout/layout.component'; export * from './lib/components/stream/stream.component';