openvidu-components: Updated projection strategy

Replaces ng-templates by a custom structural directive
pull/707/head
csantosm 2022-02-11 13:18:50 +01:00
parent bb8f0b752f
commit 2d293a689e
12 changed files with 125 additions and 167 deletions

View File

@ -5,12 +5,8 @@
*ngFor="let stream of localParticipant | connections"
[ngClass]="{ OV_small: !stream.streamManager?.stream?.videoActive }"
>
<ng-container *ngTemplateOutlet="streamTemplate; context: { stream: stream }"></ng-container>
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: stream }"></ng-container>
</div>
<!-- <ng-template #stream let-stream="stream">
<p>{{prueba.videoEnlarged}}</p>
<ov-stream [participant]="prueba"></ov-stream>
</ng-template> -->
<div
*ngFor="let stream of remoteParticipants | connections"
@ -18,6 +14,6 @@
id="remote-participant"
[ngClass]="{ OV_small: !stream.streamManager?.stream?.videoActive }"
>
<ng-container *ngTemplateOutlet="streamTemplate; context: { stream: stream }"></ng-container>
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: stream }"></ng-container>
</div>
</div>

View File

@ -1,9 +1,6 @@
<!-- Custom chat panel -->
<ng-container *ngIf="chatPanelTemplate && isChatPanelOpened">
<ng-container *ngTemplateOutlet="chatPanelTemplate"></ng-container>
</ng-container>
<!-- CHAT panel -->
<ng-content select="[chatPanel]" *ngIf="isChatPanelOpened"></ng-content>
<!-- PARTICIPANTS panel -->
<ng-content select="[participantsPanel]" *ngIf="isParticipantsPanelOpened"></ng-content>
<!-- Custom participants panel -->
<ng-container *ngIf="participantsPanelTemplate && isParticipantsPanelOpened">
<ng-container *ngTemplateOutlet="participantsPanelTemplate"></ng-container>
</ng-container>

View File

@ -9,14 +9,14 @@
fixedTopGap="0"
fixedBottomGap="0"
>
<!-- OPENVIDU PANEL -->
<ng-container *ngIf="panelTemplate">
<ng-container *ngTemplateOutlet="panelTemplate"></ng-container>
</ng-container>
<ng-content select="[panel]"></ng-content>
</mat-sidenav>
<!-- OPENVIDU LAYOUT -->
<mat-sidenav-content class="sidenav-main">
<!-- OPENVIDU LAYOUT -->
<ng-container *ngIf="layoutTemplate">
<div id="layout-container">
<ng-container *ngTemplateOutlet="layoutTemplate"></ng-container>
@ -26,9 +26,13 @@
</mat-sidenav-container>
<!-- OPENVIDU TOOLBAR -->
<ng-container *ngIf="toolbarTemplate">
<div id="footer-container">
<ng-container *ngTemplateOutlet="toolbarTemplate"></ng-container>
<span #toolbarRef>
<!-- Custom toolbar -->
<ng-content select="[toolbar]"></ng-content>
</span>
<!-- Default toolbar if custom toolbar is not injected -->
<ov-toolbar *ngIf="toolbarRef.childNodes.length === 0"></ov-toolbar>
</div>
</ng-container>
</div>

View File

@ -24,9 +24,7 @@ import { SidenavMenuService } from '../../services/sidenav-menu/sidenav-menu.ser
styleUrls: ['./session.component.css']
})
export class SessionComponent implements OnInit, AfterViewInit {
@ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef<any>;
@ContentChild('layout', { read: TemplateRef }) layoutTemplate: TemplateRef<any>;
@ContentChild('panel', { read: TemplateRef }) panelTemplate: TemplateRef<any>;
@Input() tokens: { webcam: string; screen: string };
@Output() _session = new EventEmitter<any>();

View File

@ -15,83 +15,54 @@
<div id="session-container" *ngIf="joinSessionClicked && isSessionAlive && !error">
<ov-session [tokens]="_tokens">
<ng-content select="[toolbar]" toolbar></ng-content>
<!-- Toolbar container injection -->
<ng-template #toolbar>
<!-- Custom toolbar -->
<ng-container *ngIf="toolbarTemplate; else defaultToolbar">
<ng-container *ngTemplateOutlet="toolbarTemplate"></ng-container>
</ng-container>
<!-- Default toolbar if custom toolbar is not injected -->
<ng-template #defaultToolbar>
<ov-toolbar></ov-toolbar>
</ng-template>
</ng-template>
<ng-template #panel>
<!-- OPENVIDU PANEL -->
<span #panelRef panel>
<!-- Custom panel -->
<ng-container *ngIf="panelTemplate; else defaultPanel">
<ng-container *ngTemplateOutlet="panelTemplate"></ng-container>
</ng-container>
<ng-content select="[panel]"></ng-content>
</span>
<!-- Default panel if custom panel is not injected -->
<ng-template #defaultPanel>
<ov-panel>
<!-- CHAT panel -->
<ng-template #chatPanel>
<ng-container *ngIf="chatPanelTemplate; else defaultChatPanel">
<ng-container *ngTemplateOutlet="chatPanelTemplate"></ng-container>
</ng-container>
<!-- Default panel if the custom one is not injected -->
<ov-panel *ngIf="panelRef.childNodes.length === 0" panel>
<span #chatPanelRef chatPanel>
<!-- Custom CHAT panel -->
<ng-content select="[chatPanel]"></ng-content>
</span>
<ng-template #defaultChatPanel>
<ov-chat-panel></ov-chat-panel>
</ng-template>
</ng-template>
<!-- Default CHAT PANEL if the custom one is not injected -->
<ov-chat-panel *ngIf="chatPanelRef.childNodes.length === 0" chatPanel></ov-chat-panel>
<!-- PARTICIPANTS panel -->
<ng-template #participantsPanel>
<ng-container *ngIf="participantsPanelTemplate; else defaultParticipantsPanel">
<ng-container *ngTemplateOutlet="participantsPanelTemplate"></ng-container>
</ng-container>
<ng-template #defaultParticipantsPanel>
<ov-participants-panel></ov-participants-panel>
</ng-template>
</ng-template>
<span #participantsPanelRef participantsPanel>
<!-- Custom PARTICIPANTS panel -->
<ng-content select="[participantsPanel]"></ng-content>
</span>
<!-- Default PARTICIPANTS PANEL if the custom one is not injected -->
<ov-participants-panel *ngIf="participantsPanelRef.childNodes.length === 0" participantsPanel></ov-participants-panel>
</ov-panel>
</ng-template>
</ng-template>
<!-- Layout container injection -->
<ng-template #layout>
<!-- Custom layout -->
<ng-container *ngIf="layoutTemplate; else defaultLayout">
<ng-container *ngTemplateOutlet="layoutTemplate"></ng-container>
</ng-container>
<span #layoutRef layout>
<ng-content select="[layout]"></ng-content>
</span>
<!-- Default layout if custom layout is not injected -->
<ng-template #defaultLayout>
<ov-layout>
<ng-template #stream let-stream="stream">
<ov-layout *ngIf="layoutRef.childNodes.length === 0" layout>
<ng-template #stream let-stream>
<!-- Custom stream component -->
<!-- We must to bind a context for the 'participant' input property -->
<ng-container *ngIf="streamTemplate; else defaultStream">
<ng-container *ngTemplateOutlet="streamTemplate;context:{stream:stream}"></ng-container>
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: stream }"> </ng-container>
</ng-container>
<!-- Default stream component if custom component is not injected -->
<!-- We must to bind a context for the 'participant' input property -->
<!-- Default stream component if custom one is not injected -->
<ng-template #defaultStream>
<ov-stream [stream]="stream"></ov-stream>
</ng-template>
</ng-template>
</ov-layout>
</ng-template>
</ng-template>
</ov-session>
</div>
</div>

View File

@ -1,4 +1,5 @@
import { Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateRef } from '@angular/core';
import { Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
import { StreamDirective } from '../../directives/stream/stream.directive';
@Component({
selector: 'ov-videoconference',
@ -6,16 +7,38 @@ import { Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateR
styleUrls: ['./videoconference.component.css']
})
export class VideoconferenceComponent implements OnInit {
@ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate: TemplateRef<any>;
@ContentChild('layout', { read: TemplateRef }) layoutTemplate: TemplateRef<any>;
@ContentChild('panel', { read: TemplateRef }) panelTemplate: TemplateRef<any>;
@ContentChild('chatPanel', { read: TemplateRef }) chatPanelTemplate: TemplateRef<any>;
@ContentChild('participantsPanel', { read: TemplateRef }) participantsPanelTemplate: TemplateRef<any>;
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
streamTemplate: TemplateRef<any>;
// @ContentChild('layout', { read: TemplateRef }) layoutTemplate: TemplateRef<any>;
@ContentChild(StreamDirective)
set customStream(customStream: StreamDirective) {
if (customStream) {
this.streamTemplate = customStream.template;
}
}
@Input() sessionName: string;
@Input() userName: string;
@Input()
set tokens(tokens: { webcam: string; screen: string }) {
if (!tokens || (!tokens.webcam && !tokens.screen)) {
//No tokens received
// throw new Error('No tokens received');
console.warn('No tokens received');
} else {
if (tokens.webcam || tokens.screen) {
this._tokens = {
webcam: tokens.webcam,
screen: tokens.screen
};
this.joinSessionClicked = true;
this.isSessionAlive = true;
}
}
}
// @Input() openviduServerUrl: string;
// @Input() openviduSecret: string;
@ -33,25 +56,6 @@ export class VideoconferenceComponent implements OnInit {
ngOnInit() {}
@Input()
set tokens(tokens: { webcam: string; screen: string }) {
if (!tokens || (!tokens.webcam && !tokens.screen)) {
//No tokens received
// throw new Error('No tokens received');
console.warn('No tokens received');
} else {
if (tokens.webcam || tokens.screen) {
this._tokens = {
webcam: tokens.webcam,
screen: tokens.screen
};
this.joinSessionClicked = true;
this.isSessionAlive = true;
}
}
}
async _onJoinClicked() {
this.onJoinClicked.emit();
}

View File

@ -0,0 +1,8 @@
import { StreamDirective } from './stream.directive';
describe('StreamDirective', () => {
it('should create an instance', () => {
const directive = new StreamDirective();
expect(directive).toBeTruthy();
});
});

View File

@ -0,0 +1,10 @@
import { Directive, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[ovStream]'
})
export class StreamDirective implements OnInit {
constructor(public template: TemplateRef<any>, public container: ViewContainerRef) {}
ngOnInit() {}
}

View File

@ -58,9 +58,13 @@ import { ParticipantItemComponent } from './components/panel/participants-panel/
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';
import { StreamDirective } from './directives/stream/stream.directive';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
declarations: [
StreamDirective,
UserSettingsComponent,
VideoComponent,
ToolbarComponent,
@ -77,7 +81,7 @@ import { PanelComponent } from './components/panel/panel.component';
ParticipantItemComponent,
ParticipantsPanelComponent,
VideoconferenceComponent,
PanelComponent
PanelComponent,
],
imports: [
CommonModule,
@ -132,7 +136,8 @@ import { PanelComponent } from './components/panel/panel.component';
StreamComponent,
VideoComponent,
ParticipantConnectionsPipe,
CommonModule
CommonModule,
StreamDirective
],
entryComponents: [DialogTemplateComponent]
})

View File

@ -40,3 +40,6 @@ export * from './lib/models/notification-options.model';
// Pipes
export * from './lib/pipes/participant-connections.pipe';
// Directives
export * from './lib/directives/stream/stream.directive';

View File

@ -1,61 +1,22 @@
<!-- <div id="call-container">
<div id="userSettings" *ngIf="!joinSessionClicked && !closeClicked || !isSessionAlive">
<ov-user-settings (onJoinClicked)="onJoinClicked()" (onCloseClicked)="onCloseClicked()"></ov-user-settings>
</div>
<div *ngIf="joinSessionClicked && isSessionAlive" style="height: 100%;">
<ov-session [tokens]="tokens">
<ng-template #toolbar>
<ov-toolbar
(onCamClicked)="onCamClicked()"
(onMicClicked)="onMicClicked()"
(onScreenShareClicked)="onScreenShareClicked()"
(onSpeakerLayoutClicked)="onSpeakerLayoutClicked()"
(onLeaveSessionClicked)="onLeaveSessionClicked()"
></ov-toolbar>
</ng-template>
<ov-layout layout></ov-layout>
</ov-session>
</div>
</div> -->
<ov-videoconference (onJoinClicked)="onJoinClicked()" [tokens]="tokens">
<!-- <ng-template #toolbar>
<ov-toolbar postion="top" (onCamClicked)="onCamClicked()"></ov-toolbar>
</ng-template> -->
<!-- <ng-template #layout>
<ov-toolbar postion="top" (onCamClicked)="onCamClicked()"></ov-toolbar>
</ng-template> -->
<!-- <ov-toolbar toolbar (onCamClicked)="onCamClicked()"></ov-toolbar> -->
<!-- <ng-template #panel>
<ov-toolbar postion="top" (onCamClicked)="onCamClicked()"></ov-toolbar>
</ng-template> -->
<!-- <ov-toolbar panel (onCamClicked)="onCamClicked()"></ov-toolbar> -->
<!-- <ov-toolbar chatPanel (onCamClicked)="onCamClicked()"></ov-toolbar> -->
<!-- <ov-toolbar participantsPanel (onCamClicked)="onCamClicked()"></ov-toolbar> -->
<!-- <ng-template #chatPanel>
<ov-toolbar postion="top" (onCamClicked)="onCamClicked()"></ov-toolbar>
</ng-template> -->
<!-- <ng-template #participantsPanel>
<ov-toolbar postion="top" (onCamClicked)="onCamClicked()"></ov-toolbar>
</ng-template> -->
<!-- <ov-toolbar layout (onCamClicked)="onCamClicked()"></ov-toolbar> -->
<!-- <ng-template #stream let-stream="stream">
<ov-stream postion="top" [stream]="stream">
<button network-quality> hola</button>
<ng-template #notification>
<button mat-icon-button id="hand-notification" *ngIf="stream.videoEnlarged">
<mat-icon>front_hand</mat-icon>
</button>
</ng-template>
</ov-stream>
</ng-template> -->
<!-- <div *ovStream="let stream">
<p>{{stream.videoEnlarged}}</p>
<ov-stream [stream]="stream"></ov-stream>
</div> -->
</ov-videoconference>

View File

@ -1,13 +1,14 @@
import { Component, OnInit } from '@angular/core';
import { Component, ContentChild, OnInit } from '@angular/core';
import { RestService } from '../services/rest.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-call',
templateUrl: './call.component.html',
styleUrls: ['./call.component.scss']
})
export class CallComponent implements OnInit {
sessionId = 'prueba-majestuosa-amable';
tokens: { webcam: string; screen: string };