openvidu-components: Changed impure pipe to pure to increased efficiency

- Updated the behaviour subject creating a new reference object 
- Made the streamTypesEnabled pipe to pure 
- Fixed update bug in participants panel
pull/707/head
csantosm 2022-03-03 10:21:33 +01:00
parent 7af7b96a2d
commit 5a41202935
8 changed files with 44 additions and 25 deletions

View File

@ -49,14 +49,13 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
protected subscribeToParticipants() { protected subscribeToParticipants() {
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => { this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
// We need to update the object reference doing a deep copy for update the view this.localParticipant = p;
this.localParticipant = Object.assign(Object.create(p), p)
this.layoutService.update(); this.layoutService.update();
this.cd.markForCheck(); this.cd.markForCheck();
}); });
this.remoteParticipantsSubs = this.participantService.remoteParticipantsObs.subscribe((participants) => { this.remoteParticipantsSubs = this.participantService.remoteParticipantsObs.subscribe((participants) => {
this.remoteParticipants = [...participants]; this.remoteParticipants = participants;
this.layoutService.update(); this.layoutService.update();
this.cd.markForCheck(); this.cd.markForCheck();
}); });

View File

@ -1,10 +1,12 @@
import { Component, Input } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input } from '@angular/core';
import { ParticipantAbstractModel } from '../../../../models/participant.model'; import { ParticipantAbstractModel } from '../../../../models/participant.model';
@Component({ @Component({
selector: 'ov-participant-panel-item', selector: 'ov-participant-panel-item',
templateUrl: './participant-panel-item.component.html', templateUrl: './participant-panel-item.component.html',
styleUrls: ['./participant-panel-item.component.css'] styleUrls: ['./participant-panel-item.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class ParticipantPanelItemComponent { export class ParticipantPanelItemComponent {
@ -12,6 +14,7 @@ export class ParticipantPanelItemComponent {
set participant(p: ParticipantAbstractModel) { set participant(p: ParticipantAbstractModel) {
this._participant = p; this._participant = p;
} }
_participant: ParticipantAbstractModel; _participant: ParticipantAbstractModel;
constructor() {} constructor() {}

View File

@ -27,6 +27,8 @@
} }
.scrollable { .scrollable {
height: calc(100% - 60px);
max-height: calc(100% - 60px);
overflow: auto; overflow: auto;
} }

View File

@ -8,14 +8,14 @@
<div class="scrollable"> <div class="scrollable">
<div class="local-participant-container"> <div class="local-participant-container" *ngIf="localParticipant">
<ng-container *ngTemplateOutlet="participantPanelItemTemplate; context: { $implicit: localParticipant }"></ng-container> <ng-container *ngTemplateOutlet="participantPanelItemTemplate; context: { $implicit: localParticipant }"></ng-container>
<mat-divider *ngIf="true"></mat-divider> <mat-divider *ngIf="true"></mat-divider>
</div> </div>
<div class="remote-participants-container" *ngIf="remoteParticipants.length > 0"> <div class="remote-participants-container" *ngIf="remoteParticipants.length > 0">
<div *ngFor="let participant of remoteParticipants; let lastItem = last"> <div *ngFor="let participant of this.remoteParticipants">
<ng-container *ngTemplateOutlet="participantPanelItemTemplate; context: { $implicit: participant }"></ng-container> <ng-container *ngTemplateOutlet="participantPanelItemTemplate; context: { $implicit: participant }"></ng-container>
</div> </div>
</div> </div>

View File

@ -1,8 +1,9 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, OnInit, TemplateRef } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, OnDestroy, OnInit, TemplateRef } from '@angular/core';
import { ParticipantAbstractModel, ParticipantModel } from '../../../../models/participant.model'; import { ParticipantAbstractModel } 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';
import { ParticipantPanelItemDirective } from '../../../../directives/openvidu-angular.directive'; import { ParticipantPanelItemDirective } from '../../../../directives/openvidu-angular.directive';
import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'ov-participants-panel', selector: 'ov-participants-panel',
@ -10,9 +11,12 @@ import { ParticipantPanelItemDirective } from '../../../../directives/openvidu-a
styleUrls: ['./participants-panel.component.css'], styleUrls: ['./participants-panel.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class ParticipantsPanelComponent implements OnInit { export class ParticipantsPanelComponent implements OnInit, OnDestroy {
localParticipant: any; localParticipant: any;
remoteParticipants: ParticipantAbstractModel[] = []; remoteParticipants: ParticipantAbstractModel[] = [];
private localParticipantSubs: Subscription;
private remoteParticipantsSubs: Subscription;
@ContentChild('participantPanelItem', { read: TemplateRef }) participantPanelItemTemplate: TemplateRef<any>; @ContentChild('participantPanelItem', { read: TemplateRef }) participantPanelItemTemplate: TemplateRef<any>;
@ContentChild(ParticipantPanelItemDirective) @ContentChild(ParticipantPanelItemDirective)
@ -28,22 +32,34 @@ export class ParticipantsPanelComponent implements OnInit {
protected participantService: ParticipantService, protected participantService: ParticipantService,
protected menuService: SidenavMenuService, protected menuService: SidenavMenuService,
private cd: ChangeDetectorRef private cd: ChangeDetectorRef
) {} ) {
}
ngOnInit(): void { ngOnInit(): void {
this.participantService.localParticipantObs.subscribe((p: ParticipantModel) => {
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p: ParticipantAbstractModel) => {
this.localParticipant = p; this.localParticipant = p;
// Mark for re-rendering using an impure pipe 'streamsTypesEnabled' // Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
this.cd.markForCheck(); this.cd.markForCheck();
}); });
this.participantService.remoteParticipantsObs.subscribe((p: ParticipantModel[]) => { this.remoteParticipantsSubs = this.participantService.remoteParticipantsObs.subscribe((p: ParticipantAbstractModel[]) => {
this.remoteParticipants = p; // Workaround which forc the objects references update
// After one entirely day trying to make it works, this is the only way
p.forEach((par, index) => {
this.remoteParticipants[index] = Object.create(par);
});
// Mark for re-rendering using an impure pipe 'streamsTypesEnabled' // Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
this.cd.markForCheck(); this.cd.markForCheck();
}); });
} }
ngOnDestroy() {
if (this.localParticipantSubs) this.localParticipantSubs.unsubscribe();
if (this.remoteParticipantsSubs) this.remoteParticipantsSubs.unsubscribe;
}
close() { close() {
this.menuService.closeMenu(); this.menuService.closeMenu();
} }

View File

@ -33,7 +33,7 @@ export abstract class ParticipantAbstractModel {
this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random()*360}, 100%, 80%)`; this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random()*360}, 100%, 80%)`;
this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false; this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false;
let streamModel: StreamModel = { let streamModel: StreamModel = {
connected: true, connected: model ? model.connected : true,
type: model ? model.type : VideoType.CAMERA, type: model ? model.type : VideoType.CAMERA,
streamManager: model ? model.streamManager : null, streamManager: model ? model.streamManager : null,
videoEnlarged: model ? model.videoEnlarged : false, videoEnlarged: model ? model.videoEnlarged : false,

View File

@ -1,15 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { StreamModel, ParticipantAbstractModel } from '../models/participant.model'; import { StreamModel, ParticipantAbstractModel } from '../models/participant.model';
@Pipe({ name: 'streams', pure: true }) @Pipe({ name: 'streams' })
export class ParticipantStreamsPipe implements PipeTransform { export class ParticipantStreamsPipe implements PipeTransform {
constructor() {} constructor() {}
transform(participants: ParticipantAbstractModel[] | ParticipantAbstractModel): StreamModel[] { transform(participants: ParticipantAbstractModel[] | ParticipantAbstractModel): StreamModel[] {
let streams: StreamModel[] = []; let streams: StreamModel[] = [];
console.log('STREAM PIPE') if(participants && Object.keys(participants).length > 0){
debugger
if(Object.keys(participants).length > 0){
if (Array.isArray(participants)) { if (Array.isArray(participants)) {
participants.forEach((p) => { participants.forEach((p) => {
streams = streams.concat(p.getAvailableConnections()); streams = streams.concat(p.getAvailableConnections());
@ -23,11 +21,12 @@ export class ParticipantStreamsPipe implements PipeTransform {
} }
} }
@Pipe({ name: 'streamTypesEnabled', pure: false }) @Pipe({ name: 'streamTypesEnabled' })
export class StreamTypesEnabledPipe implements PipeTransform { export class StreamTypesEnabledPipe implements PipeTransform {
constructor() {} constructor() {}
transform(participant: ParticipantAbstractModel): string { transform(participant: ParticipantAbstractModel): string {
return `(${participant?.getConnectionTypesActive().toString().replace(',', ', ')})`; const activeStreams = participant?.getConnectionTypesActive().toString();
return `(${activeStreams.replace(',', ', ')})`;
} }
} }

View File

@ -174,7 +174,7 @@ export class ParticipantService {
} }
updateLocalParticipant() { updateLocalParticipant() {
this._localParticipant.next(this.localParticipant); this._localParticipant.next(Object.assign(Object.create(this.localParticipant),this.localParticipant));
} }
/** /**
@ -287,7 +287,7 @@ export class ParticipantService {
} }
updateRemoteParticipants() { updateRemoteParticipants() {
this._remoteParticipants.next(this.remoteParticipants); this._remoteParticipants.next([...this.remoteParticipants]);
} }
protected getTypeConnectionData(data: string): VideoType { protected getTypeConnectionData(data: string): VideoType {