openvidu-components: Created participant from pre-join component

* Refactored update local participant method
* Refactored pipes
pull/707/head
csantosm 2022-03-02 17:35:14 +01:00
parent b4decda1f5
commit 7af7b96a2d
8 changed files with 60 additions and 41 deletions

View File

@ -31,7 +31,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(protected layoutService: LayoutService, protected participantService: ParticipantService, private cd: ChangeDetectorRef) {} constructor(protected layoutService: LayoutService, protected participantService: ParticipantService, private cd: ChangeDetectorRef) {}
ngOnInit(): void { ngOnInit(): void {
this.subscribeToUsers(); this.subscribeToParticipants();
} }
ngAfterViewInit() { ngAfterViewInit() {
@ -47,9 +47,10 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
this.layoutService.clear(); this.layoutService.clear();
} }
protected subscribeToUsers() { protected subscribeToParticipants() {
this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => { this.localParticipantSubs = this.participantService.localParticipantObs.subscribe((p) => {
this.localParticipant = p; // We need to update the object reference doing a deep copy for update the view
this.localParticipant = Object.assign(Object.create(p), p)
this.layoutService.update(); this.layoutService.update();
this.cd.markForCheck(); this.cd.markForCheck();
}); });

View File

@ -2,7 +2,7 @@
<mat-list-item> <mat-list-item>
<mat-icon matListAvatar class="participant-avatar">person</mat-icon> <mat-icon matListAvatar class="participant-avatar">person</mat-icon>
<h3 matLine class="participant-nickname">{{ _participant.nickname }}</h3> <h3 matLine class="participant-nickname">{{ _participant.nickname }}</h3>
<p matLine class="participant-subtitle">{{ _participant | streamsEnabled }}</p> <p matLine class="participant-subtitle">{{ _participant | streamTypesEnabled }}</p>
<!-- <p matLine> <!-- <p matLine>
<span class="participant-subtitle"></span> <span class="participant-subtitle"></span>
</p> --> </p> -->

View File

@ -33,13 +33,13 @@ export class ParticipantsPanelComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.participantService.localParticipantObs.subscribe((p: ParticipantModel) => { this.participantService.localParticipantObs.subscribe((p: ParticipantModel) => {
this.localParticipant = p; this.localParticipant = p;
// Mark for re-rendering using an impure pipe 'streamsEnabled' // Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
this.cd.markForCheck(); this.cd.markForCheck();
}); });
this.participantService.remoteParticipantsObs.subscribe((p: ParticipantModel[]) => { this.participantService.remoteParticipantsObs.subscribe((p: ParticipantModel[]) => {
this.remoteParticipants = p; this.remoteParticipants = p;
// Mark for re-rendering using an impure pipe 'streamsEnabled' // Mark for re-rendering using an impure pipe 'streamsTypesEnabled'
this.cd.markForCheck(); this.cd.markForCheck();
}); });
} }

View File

@ -4,7 +4,7 @@ import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/O
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { CustomDevice } from '../../models/device.model'; import { CustomDevice } from '../../models/device.model';
import { ILogger } from '../../models/logger.model'; import { ILogger } from '../../models/logger.model';
import { ParticipantAbstractModel } from '../../models/participant.model'; import { ParticipantAbstractModel, ParticipantProperties } from '../../models/participant.model';
import { ActionService } from '../../services/action/action.service'; import { ActionService } from '../../services/action/action.service';
import { DeviceService } from '../../services/device/device.service'; import { DeviceService } from '../../services/device/device.service';
import { LayoutService } from '../../services/layout/layout.service'; import { LayoutService } from '../../services/layout/layout.service';
@ -57,10 +57,15 @@ export class PreJoinComponent implements OnInit, OnDestroy {
async ngOnInit() { async ngOnInit() {
await this.deviceSrv.initializeDevices(); await this.deviceSrv.initializeDevices();
this.nickname = this.storageSrv.getNickname() || this.generateRandomNickname();
const props: ParticipantProperties = {
local: true,
nickname: this.nickname
};
this.participantService.initLocalParticipant(props);
this.subscribeToLocalParticipantEvents(); this.subscribeToLocalParticipantEvents();
this.openviduService.initialize(); this.openviduService.initialize();
this.nickname = this.storageSrv.getNickname() || this.generateRandomNickname();
this.windowSize = window.innerWidth; this.windowSize = window.innerWidth;
this.setDevicesInfo(); this.setDevicesInfo();
if (this.hasAudioDevices || this.hasVideoDevices) { if (this.hasAudioDevices || this.hasVideoDevices) {

View File

@ -10,6 +10,14 @@ export interface StreamModel {
participant?: ParticipantAbstractModel participant?: ParticipantAbstractModel
} }
export interface ParticipantProperties {
local: boolean;
nickname: string;
id?: string;
colorProfile?: string;
isMutedForcibly?: boolean;
}
export abstract class ParticipantAbstractModel { export abstract class ParticipantAbstractModel {
streams: Map<VideoType, StreamModel> = new Map(); streams: Map<VideoType, StreamModel> = new Map();
id: string; id: string;
@ -18,12 +26,12 @@ export abstract class ParticipantAbstractModel {
colorProfile: string; colorProfile: string;
isMutedForcibly: boolean; isMutedForcibly: boolean;
constructor(model?: StreamModel, id?: string, local: boolean = true, nickname?: string) { constructor(props: ParticipantProperties, model?: StreamModel) {
this.id = id ? id : new Date().getTime().toString(); this.id = props.id ? props.id : new Date().getTime().toString();
this.local = local, this.local = props.local;
this.nickname = nickname ? nickname : 'OpenVidu_User'; this.nickname = props.nickname;
this.colorProfile = `hsl(${Math.random()*360}, 100%, 80%)`; this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random()*360}, 100%, 80%)`;
this.isMutedForcibly = false; this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false;
let streamModel: StreamModel = { let streamModel: StreamModel = {
connected: true, connected: true,
type: model ? model.type : VideoType.CAMERA, type: model ? model.type : VideoType.CAMERA,

View File

@ -36,7 +36,7 @@ import { StreamComponent } from './components/stream/stream.component';
import { DialogTemplateComponent } from './components/material/dialog.component'; import { DialogTemplateComponent } from './components/material/dialog.component';
import { LinkifyPipe } from './pipes/linkify.pipe'; import { LinkifyPipe } from './pipes/linkify.pipe';
import { StreamsEnabledPipe, ParticipantStreamsPipe } from './pipes/participant.pipe'; import { StreamTypesEnabledPipe, ParticipantStreamsPipe } from './pipes/participant.pipe';
import { OpenViduAngularConfig } from './config/openvidu-angular.config'; import { OpenViduAngularConfig } from './config/openvidu-angular.config';
import { CdkOverlayContainer } from './config/custom-cdk-overlay'; import { CdkOverlayContainer } from './config/custom-cdk-overlay';
@ -83,7 +83,7 @@ import { AvatarProfileComponent } from './components/avatar-profile/avatar-profi
DialogTemplateComponent, DialogTemplateComponent,
LinkifyPipe, LinkifyPipe,
ParticipantStreamsPipe, ParticipantStreamsPipe,
StreamsEnabledPipe, StreamTypesEnabledPipe,
ParticipantPanelItemComponent, ParticipantPanelItemComponent,
ParticipantsPanelComponent, ParticipantsPanelComponent,
VideoconferenceComponent, VideoconferenceComponent,
@ -157,7 +157,7 @@ import { AvatarProfileComponent } from './components/avatar-profile/avatar-profi
AudioWaveComponent, AudioWaveComponent,
PreJoinComponent, PreJoinComponent,
ParticipantStreamsPipe, ParticipantStreamsPipe,
StreamsEnabledPipe, StreamTypesEnabledPipe,
CommonModule, CommonModule,
ToolbarDirective, ToolbarDirective,
PanelDirective, PanelDirective,

View File

@ -1,25 +1,30 @@
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' }) @Pipe({ name: 'streams', pure: true })
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')
debugger
if(Object.keys(participants).length > 0){
if (Array.isArray(participants)) { if (Array.isArray(participants)) {
participants.forEach((p) => { participants.forEach((p) => {
streams = streams.concat(Array.from(p.streams.values())); streams = streams.concat(p.getAvailableConnections());
}); });
} else { } else {
streams = Array.from(participants.streams.values());
streams = participants.getAvailableConnections();
}
} }
return streams; return streams;
} }
} }
@Pipe({ name: 'streamsEnabled', pure: false }) @Pipe({ name: 'streamTypesEnabled', pure: false })
export class StreamsEnabledPipe implements PipeTransform { export class StreamTypesEnabledPipe implements PipeTransform {
constructor() {} constructor() {}
transform(participant: ParticipantAbstractModel): string { transform(participant: ParticipantAbstractModel): string {

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { Publisher, Subscriber } from 'openvidu-browser'; import { Publisher, Subscriber } from 'openvidu-browser';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { ILogger } from '../../models/logger.model'; import { ILogger } from '../../models/logger.model';
import { StreamModel, ParticipantAbstractModel, ParticipantModel } from '../../models/participant.model'; import { StreamModel, ParticipantAbstractModel, ParticipantModel, ParticipantProperties } from '../../models/participant.model';
import { VideoType } from '../../models/video-type.model'; import { VideoType } from '../../models/video-type.model';
import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.service'; import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.service';
import { LoggerService } from '../logger/logger.service'; import { LoggerService } from '../logger/logger.service';
@ -29,8 +29,10 @@ export class ParticipantService {
this.localParticipantObs = this._localParticipant.asObservable(); this.localParticipantObs = this._localParticipant.asObservable();
this.remoteParticipantsObs = this._remoteParticipants.asObservable(); this.remoteParticipantsObs = this._remoteParticipants.asObservable();
}
this.localParticipant = this.newParticipant(); initLocalParticipant(props: ParticipantProperties) {
this.localParticipant = this.newParticipant(props);
this.updateLocalParticipant(); this.updateLocalParticipant();
} }
@ -131,7 +133,7 @@ export class ParticipantService {
clear() { clear() {
this.disableScreenUser(); this.disableScreenUser();
this.localParticipant = this.newParticipant(); // this.localParticipant = this.newParticipant();
// this._screensharing.next(false); // this._screensharing.next(false);
this.remoteParticipants = []; this.remoteParticipants = [];
this._remoteParticipants = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]); this._remoteParticipants = <BehaviorSubject<ParticipantAbstractModel[]>>new BehaviorSubject([]);
@ -172,12 +174,7 @@ export class ParticipantService {
} }
updateLocalParticipant() { updateLocalParticipant() {
// Cloning localParticipant object for not applying changes on the global variable this._localParticipant.next(this.localParticipant);
let participantsWithConnectionAvailable: ParticipantAbstractModel = Object.assign(this.newParticipant(), this.localParticipant);
const availableConnections = participantsWithConnectionAvailable.getAvailableConnections();
const availableConnectionsMap = new Map(availableConnections.map((conn) => [conn.type, conn]));
participantsWithConnectionAvailable.streams = availableConnectionsMap;
this._localParticipant.next(participantsWithConnectionAvailable);
} }
/** /**
@ -210,9 +207,12 @@ export class ParticipantService {
} }
} else { } else {
this.log.w('Creating new participant with id: ', participantId); this.log.w('Creating new participant with id: ', participantId);
const nickname = this.getNicknameFromConnectionData(data); const props: ParticipantProperties = {
const local = false; nickname: this.getNicknameFromConnectionData(data),
const remoteParticipant = this.newParticipant(streamModel, participantId, local, nickname); local: false,
id: participantId
}
const remoteParticipant = this.newParticipant(props, streamModel);
this.remoteParticipants.push(remoteParticipant); this.remoteParticipants.push(remoteParticipant);
} }
this.updateRemoteParticipants(); this.updateRemoteParticipants();
@ -306,11 +306,11 @@ export class ParticipantService {
} }
} }
protected newParticipant(streamModel?: StreamModel, participantId?: string, local?: boolean, nickname?: string) { protected newParticipant(props: ParticipantProperties, streamModel?: StreamModel) {
if(this.openviduAngularConfigSrv.hasParticipantFactory()){ if(this.openviduAngularConfigSrv.hasParticipantFactory()){
return this.openviduAngularConfigSrv.getParticipantFactory().apply(this, [streamModel, participantId, local, nickname]); return this.openviduAngularConfigSrv.getParticipantFactory().apply(this, [props, streamModel]);
} }
return new ParticipantModel(streamModel, participantId, local, nickname); return new ParticipantModel(props, streamModel);
} }
} }