mirror of https://github.com/OpenVidu/openvidu.git
openvidu-components: Replaced user-settings component to pre-join
parent
d29f650b02
commit
1279962555
|
@ -1,4 +1,4 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, OnDestroy, OnInit, TemplateRef } from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, OnDestroy, OnInit, TemplateRef } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ParticipantService } from '../../services/participant/participant.service';
|
||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
|
@ -11,7 +11,7 @@ import { StreamDirective } from '../../directives/openvidu-angular.directive';
|
|||
styleUrls: ['./layout.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class LayoutComponent implements OnInit, OnDestroy {
|
||||
export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
|
||||
|
||||
@ContentChild(StreamDirective)
|
||||
|
@ -32,6 +32,9 @@ export class LayoutComponent implements OnInit, OnDestroy {
|
|||
|
||||
ngOnInit(): void {
|
||||
this.subscribeToUsers();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.layoutService.initialize();
|
||||
this.layoutService.update();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
.container {
|
||||
height: 100%;
|
||||
padding: 80px;
|
||||
background-color: var(--ov-light-dark-color);
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom: 1px;
|
||||
font-weight: bold;
|
||||
}
|
||||
hr {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ov-layout {
|
||||
height: -webkit-fill-available;
|
||||
height: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: -moz-available;
|
||||
}
|
||||
|
||||
.media-panel {
|
||||
background-color: var(--ov-light-dark-color);
|
||||
}
|
||||
.media-panel-container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.nickname-container {
|
||||
/* padding: 10px; */
|
||||
display: block !important;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
#nickname-input-container, .device-container-element {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#nickname-input-container button, .device-container-element button {
|
||||
margin: auto 10px auto auto;
|
||||
}
|
||||
|
||||
|
||||
#nickname-input-container button.mat-button-disabled {
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
|
||||
#nickname-input-container mat-form-field, .device-container-element mat-form-field {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
color: var(--ov-primary-color);
|
||||
}
|
||||
|
||||
#nickname-input-container mat-form-field {
|
||||
color: var(--ov-primary-color);
|
||||
}
|
||||
|
||||
.mat-form-field-appearance-fill .mat-form-field-flex {
|
||||
background-color: var(--ov-light-color);
|
||||
border-radius: var(--ov-video-radius);
|
||||
}
|
||||
|
||||
|
||||
.buttons-container{
|
||||
border-radius: 5px;
|
||||
padding: 10px 0px;
|
||||
height: 100px;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#camera-button {
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
/* background-color: var(--ov-secondary-color) !important; */
|
||||
/* color: var(--ov-light-color) !important; */
|
||||
|
||||
}
|
||||
|
||||
.join-btn-container {
|
||||
width: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#join-button {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
color: var(--ov-light-color);
|
||||
background-color: var(--ov-tertiary-color);
|
||||
border-radius: var(--ov-video-radius);
|
||||
|
||||
}
|
||||
|
||||
.warn-btn {
|
||||
color: var(--ov-light-color);
|
||||
background-color: var(--ov-warn-color) !important;
|
||||
}
|
||||
|
||||
.active-btn {
|
||||
color: var(--ov-light-color);
|
||||
background-color: var(--ov-tertiary-color) !important;
|
||||
}
|
||||
.media-btn {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
::ng-deep .mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
|
||||
padding: 1px !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-input-element {
|
||||
caret-color: #000000;
|
||||
}
|
||||
::ng-deep .mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.container, .media-panel-container, .buttons-container {
|
||||
padding: 0;
|
||||
}
|
||||
.nickname-container, .buttons-container, .join-btn-container {
|
||||
width: 90% !important;
|
||||
margin: auto;
|
||||
}
|
||||
.join-btn-container {
|
||||
padding: 0px 10px;
|
||||
}
|
||||
.media-panel {
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 480px) and (max-width: 960px) {
|
||||
.container, .media-panel-container, .buttons-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nickname-container, .buttons-container, .join-btn-container{
|
||||
width: 80% !important;
|
||||
min-width: 80% !important;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.buttons-container, .media-panel-container {
|
||||
padding-top: 0px;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.media-panel {
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<div class="container" fxLayout.gt-sm="row" fxLayout.lt-md="column">
|
||||
<div fxFlex.gt-sm="65%" fxFlex.lt-md="55%" fxLayoutAlign="center center">
|
||||
<ov-layout>
|
||||
<ng-template #stream let-stream>
|
||||
<ov-stream [stream]="stream" [showNickname]="false" [showSettings]="false"></ov-stream>
|
||||
</ng-template>
|
||||
</ov-layout>
|
||||
</div>
|
||||
<div fxFlex.gt-sm="35%" fxFlex.lt-md="45%" fxLayoutAlign="center center" class="media-panel">
|
||||
<div fxLayout="column" fxLayoutGap="10px" class="media-panel-container">
|
||||
<div fxLayout.gt-sm="column" fxLayout.lt-md="column" fxLayoutGap="10px" fxFlex="33%">
|
||||
<div fxFlex.gt-sm="100%" fxFlex.lt-md="33%" fxLayoutAlign="center center" fxFlexFill class="nickname-container">
|
||||
<h4 *ngIf="windowSize >= 960">Set your name</h4>
|
||||
<hr *ngIf="windowSize >= 960"/>
|
||||
<div id="nickname-input-container">
|
||||
<button mat-icon-button disabled>
|
||||
<mat-icon>person</mat-icon>
|
||||
</button>
|
||||
<mat-form-field appearance="standard">
|
||||
<mat-label>Nickname</mat-label>
|
||||
<input matInput type="text" maxlength="20" [(ngModel)]="nickname" (change)="updateNickname()" autocomplete="off" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- <mat-button-toggle-group style="border-radius: 20px">
|
||||
<button mat-icon-button class="media-btn">
|
||||
<mat-icon matTooltip="Mute your audio">mic</mat-icon>
|
||||
</button>
|
||||
<mat-button-toggle class="split-button-1 drop-down-button" [matMenuTriggerFor]="dropdownMenuOne">
|
||||
<mat-icon>arrow_drop_down</mat-icon>
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
|
||||
<mat-menu #dropdownMenuOne="matMenu">
|
||||
<button mat-menu-item>One</button>
|
||||
<button mat-menu-item>Two</button>
|
||||
<button mat-menu-item>Three</button>
|
||||
</mat-menu> -->
|
||||
</div>
|
||||
|
||||
<div fxFlex.gt-sm="100%" fxFlex.lt-md="33%" fxLayoutAlign="center center" fxFlexFill class="buttons-container">
|
||||
<h4 *ngIf="windowSize >= 960">Choose your devices</h4>
|
||||
<hr *ngIf="windowSize >= 960"/>
|
||||
<!-- Camera -->
|
||||
<div class="device-container-element">
|
||||
<button
|
||||
mat-icon-button
|
||||
id="camera-button"
|
||||
[disabled]="!hasVideoDevices"
|
||||
[class.warn-btn]="isVideoMuted"
|
||||
(click)="toggleCam()"
|
||||
>
|
||||
<mat-icon *ngIf="!isVideoMuted" matTooltip="Mute Camera">videocam</mat-icon>
|
||||
<mat-icon *ngIf="isVideoMuted" matTooltip="Unmute Camera">videocam_off</mat-icon>
|
||||
</button>
|
||||
<mat-form-field>
|
||||
<mat-label>Video devices</mat-label>
|
||||
<mat-select [disabled]="isVideoMuted || !hasVideoDevices" [value]="cameraSelected?.device" (selectionChange)="onCameraSelected($event)">
|
||||
<mat-option *ngFor="let camera of cameras" [value]="camera.device">
|
||||
{{ camera.label }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<!-- Microphone -->
|
||||
<div class="device-container-element">
|
||||
<button
|
||||
mat-icon-button
|
||||
id="microhpone-button"
|
||||
[disabled]="!hasAudioDevices"
|
||||
[class.warn-btn]="isAudioMuted"
|
||||
(click)="toggleMic()"
|
||||
>
|
||||
<mat-icon *ngIf="!isAudioMuted" matTooltip="Mute Audio">mic</mat-icon>
|
||||
<mat-icon *ngIf="isAudioMuted" matTooltip="Unmute Audio">mic_off</mat-icon>
|
||||
</button>
|
||||
<mat-form-field>
|
||||
<mat-label>Audio devices</mat-label>
|
||||
<mat-select [disabled]="isAudioMuted || !hasAudioDevices" [value]="microphoneSelected?.device" (selectionChange)="onMicrophoneSelected($event)">
|
||||
<mat-option *ngFor="let microphone of microphones" [value]="microphone.device">
|
||||
{{ microphone.label }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div fxFlex.gt-sm="60%" fxLayout.lt-md="column" fxLayoutAlign="center center" fxFlexFill class="join-btn-container">
|
||||
<button mat-flat-button (click)="joinSession()" form="nicknameForm" id="join-button">Join session</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PreJoinComponent } from './pre-join.component';
|
||||
|
||||
describe('PreJoinComponent', () => {
|
||||
let component: PreJoinComponent;
|
||||
let fixture: ComponentFixture<PreJoinComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PreJoinComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PreJoinComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,283 @@
|
|||
import { Component, HostListener, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import { Publisher, PublisherProperties } from 'openvidu-browser';
|
||||
import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/OpenViduError';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CustomDevice } from '../../models/device.model';
|
||||
import { ILogger } from '../../models/logger.model';
|
||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
import { ActionService } from '../../services/action/action.service';
|
||||
import { DeviceService } from '../../services/device/device.service';
|
||||
import { LayoutService } from '../../services/layout/layout.service';
|
||||
import { LoggerService } from '../../services/logger/logger.service';
|
||||
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
||||
import { ParticipantService } from '../../services/participant/participant.service';
|
||||
import { StorageService } from '../../services/storage/storage.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ov-pre-join',
|
||||
templateUrl: './pre-join.component.html',
|
||||
styleUrls: ['./pre-join.component.css']
|
||||
})
|
||||
export class PreJoinComponent implements OnInit, OnDestroy {
|
||||
@Output() onJoinClicked = new EventEmitter<any>();
|
||||
cameras: CustomDevice[];
|
||||
microphones: CustomDevice[];
|
||||
cameraSelected: CustomDevice;
|
||||
microphoneSelected: CustomDevice;
|
||||
isVideoMuted: boolean;
|
||||
isAudioMuted: boolean;
|
||||
screenShareEnabled: boolean;
|
||||
localParticipant: ParticipantAbstractModel;
|
||||
windowSize: number;
|
||||
hasVideoDevices: boolean;
|
||||
hasAudioDevices: boolean;
|
||||
isLoading = true;
|
||||
nickname: string;
|
||||
private log: ILogger;
|
||||
private localParticipantSubscription: Subscription;
|
||||
private screenShareStateSubscription: Subscription;
|
||||
|
||||
@HostListener('window:resize')
|
||||
sizeChange() {
|
||||
this.windowSize = window.innerWidth;
|
||||
this.layoutService.update();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private layoutService: LayoutService,
|
||||
private actionService: ActionService,
|
||||
private deviceSrv: DeviceService,
|
||||
private loggerSrv: LoggerService,
|
||||
private openviduService: OpenViduService,
|
||||
private participantService: ParticipantService,
|
||||
private storageSrv: StorageService
|
||||
) {
|
||||
this.log = this.loggerSrv.get('PreJoinComponent');
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.deviceSrv.initializeDevices();
|
||||
|
||||
this.subscribeToLocalParticipantEvents();
|
||||
this.openviduService.initialize();
|
||||
this.nickname = this.storageSrv.getNickname() || this.generateRandomNickname();
|
||||
this.windowSize = window.innerWidth;
|
||||
this.setDevicesInfo();
|
||||
if (this.hasAudioDevices || this.hasVideoDevices) {
|
||||
await this.initwebcamPublisher();
|
||||
}
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.localParticipantSubscription) {
|
||||
this.localParticipantSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.screenShareStateSubscription) {
|
||||
this.screenShareStateSubscription.unsubscribe();
|
||||
}
|
||||
this.deviceSrv.clear();
|
||||
}
|
||||
|
||||
async onCameraSelected(event: any) {
|
||||
const videoSource = event?.value;
|
||||
// Is New deviceId different from the old one?
|
||||
if (this.deviceSrv.needUpdateVideoTrack(videoSource)) {
|
||||
const mirror = this.deviceSrv.cameraNeedsMirror(videoSource);
|
||||
//TODO: Uncomment this when replaceTrack issue is fixed
|
||||
// const pp: PublisherProperties = { videoSource, audioSource: false, mirror };
|
||||
// await this.openviduService.replaceTrack(VideoType.CAMERA, pp);
|
||||
// TODO: Remove this when replaceTrack issue is fixed
|
||||
const pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror };
|
||||
await this.openviduService.republishTrack(pp);
|
||||
|
||||
this.cameraSelected = videoSource;
|
||||
this.deviceSrv.setCameraSelected(this.cameraSelected);
|
||||
}
|
||||
if (this.isVideoMuted) {
|
||||
// Publish Webcam video
|
||||
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);
|
||||
this.isVideoMuted = false;
|
||||
}
|
||||
}
|
||||
|
||||
async onMicrophoneSelected(event: any) {
|
||||
const audioSource = event?.value;
|
||||
// Is New deviceId different than older?
|
||||
if (this.deviceSrv.needUpdateAudioTrack(audioSource)) {
|
||||
//TODO: Uncomment this when replaceTrack issue is fixed
|
||||
// const pp: PublisherProperties = { audioSource, videoSource: false };
|
||||
// await this.openviduService.replaceTrack(VideoType.CAMERA, pp);
|
||||
// TODO: Remove this when replaceTrack issue is fixed
|
||||
const mirror = this.deviceSrv.cameraNeedsMirror(this.cameraSelected.device);
|
||||
const pp: PublisherProperties = { videoSource: this.cameraSelected.device, audioSource, mirror };
|
||||
await this.openviduService.republishTrack(pp);
|
||||
|
||||
this.microphoneSelected = audioSource;
|
||||
this.deviceSrv.setMicSelected(this.microphoneSelected);
|
||||
}
|
||||
if (this.isAudioMuted) {
|
||||
// Enable microphone
|
||||
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), true);
|
||||
this.isAudioMuted = true;
|
||||
}
|
||||
}
|
||||
|
||||
toggleCam() {
|
||||
const publish = this.isVideoMuted;
|
||||
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publish);
|
||||
|
||||
if (this.participantService.haveICameraAndScreenActive()) {
|
||||
// Cam will not published, disable webcam with screensharing active
|
||||
this.participantService.disableWebcamUser();
|
||||
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publish);
|
||||
} else if (this.participantService.isOnlyMyScreenActive()) {
|
||||
// Cam will be published, enable webcam
|
||||
this.participantService.enableWebcamUser();
|
||||
}
|
||||
|
||||
this.isVideoMuted = !this.isVideoMuted;
|
||||
this.storageSrv.setVideoMuted(this.isVideoMuted);
|
||||
}
|
||||
|
||||
// async toggleScreenShare() {
|
||||
// // Disabling screenShare
|
||||
// if (this.participantService.haveICameraAndScreenActive()) {
|
||||
// this.participantService.disableScreenUser();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Enabling screenShare
|
||||
// if (this.participantService.isOnlyMyCameraActive()) {
|
||||
// const willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive();
|
||||
// const hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.isAudioMuted;
|
||||
// const properties: PublisherProperties = {
|
||||
// videoSource: ScreenType.SCREEN,
|
||||
// audioSource: this.hasAudioDevices ? undefined : null,
|
||||
// publishVideo: true,
|
||||
// publishAudio: hasAudio,
|
||||
// mirror: false
|
||||
// };
|
||||
// const screenPublisher = await this.openviduService.initPublisher(undefined, properties);
|
||||
|
||||
// screenPublisher.on('accessAllowed', (event) => {
|
||||
// screenPublisher.stream
|
||||
// .getMediaStream()
|
||||
// .getVideoTracks()[0]
|
||||
// .addEventListener('ended', () => {
|
||||
// this.log.d('Clicked native stop button. Stopping screen sharing');
|
||||
// this.toggleScreenShare();
|
||||
// });
|
||||
// this.participantService.activeMyScreenShare(screenPublisher);
|
||||
// if (!this.participantService.hasCameraVideoActive()) {
|
||||
// this.participantService.disableWebcamUser();
|
||||
// }
|
||||
// });
|
||||
|
||||
// screenPublisher.on('accessDenied', (error: any) => {
|
||||
// if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {
|
||||
// this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing');
|
||||
// }
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Disabling screnShare and enabling webcam
|
||||
// this.participantService.enableWebcamUser();
|
||||
// this.participantService.disableScreenUser();
|
||||
// }
|
||||
|
||||
toggleMic() {
|
||||
const publish = this.isAudioMuted;
|
||||
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), publish);
|
||||
this.isAudioMuted = !this.isAudioMuted;
|
||||
this.storageSrv.setAudioMuted(this.isAudioMuted);
|
||||
}
|
||||
|
||||
updateNickname() {
|
||||
this.nickname = this.nickname === '' ? this.generateRandomNickname() : this.nickname;
|
||||
this.participantService.setMyNickname(this.nickname);
|
||||
this.storageSrv.setNickname(this.nickname);
|
||||
}
|
||||
|
||||
joinSession() {
|
||||
this.onJoinClicked.emit();
|
||||
}
|
||||
|
||||
private setDevicesInfo() {
|
||||
this.hasVideoDevices = this.deviceSrv.hasVideoDeviceAvailable();
|
||||
this.hasAudioDevices = this.deviceSrv.hasAudioDeviceAvailable();
|
||||
this.microphones = this.deviceSrv.getMicrophones();
|
||||
this.cameras = this.deviceSrv.getCameras();
|
||||
this.cameraSelected = this.deviceSrv.getCameraSelected();
|
||||
this.microphoneSelected = this.deviceSrv.getMicrophoneSelected();
|
||||
|
||||
this.isVideoMuted = this.deviceSrv.isVideoMuted();
|
||||
this.isAudioMuted = this.deviceSrv.isAudioMuted();
|
||||
}
|
||||
|
||||
private subscribeToLocalParticipantEvents() {
|
||||
this.localParticipantSubscription = this.participantService.localParticipantObs.subscribe((p) => {
|
||||
this.localParticipant = p;
|
||||
this.screenShareEnabled = p.isScreenActive();
|
||||
});
|
||||
}
|
||||
|
||||
private async initwebcamPublisher() {
|
||||
const publisher = await this.openviduService.initDefaultPublisher(undefined);
|
||||
if (publisher) {
|
||||
// this.handlePublisherSuccess(publisher);
|
||||
this.handlePublisherError(publisher);
|
||||
}
|
||||
}
|
||||
|
||||
//? After test in Chrome and Firefox, the devices always have labels.
|
||||
//? It's not longer needed
|
||||
// private handlePublisherSuccess(publisher: Publisher) {
|
||||
// publisher.once('accessAllowed', async () => {
|
||||
// if (this.deviceSrv.areEmptyLabels()) {
|
||||
// await this.deviceSrv.forceUpdate();
|
||||
// if (this.hasAudioDevices) {
|
||||
// const audioLabel = publisher?.stream?.getMediaStream()?.getAudioTracks()[0]?.label;
|
||||
// this.deviceSrv.setMicSelected(audioLabel);
|
||||
// }
|
||||
|
||||
// if (this.hasVideoDevices) {
|
||||
// const videoLabel = publisher?.stream?.getMediaStream()?.getVideoTracks()[0]?.label;
|
||||
// this.deviceSrv.setCameraSelected(videoLabel);
|
||||
// }
|
||||
// this.setDevicesInfo();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
private handlePublisherError(publisher: Publisher) {
|
||||
publisher.once('accessDenied', (e: any) => {
|
||||
let message: string;
|
||||
if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) {
|
||||
this.log.w('Video device already in use. Disabling video device...');
|
||||
// Allow access to the room with only mic if camera device is already in use
|
||||
this.hasVideoDevices = false;
|
||||
this.deviceSrv.disableVideoDevices();
|
||||
return this.initwebcamPublisher();
|
||||
}
|
||||
if (e.name === OpenViduErrorName.DEVICE_ACCESS_DENIED) {
|
||||
message = 'Access to media devices was not allowed.';
|
||||
this.hasVideoDevices = false;
|
||||
this.hasAudioDevices = false;
|
||||
this.deviceSrv.disableVideoDevices();
|
||||
this.deviceSrv.disableAudioDevices();
|
||||
return this.initwebcamPublisher();
|
||||
} else if (e.name === OpenViduErrorName.NO_INPUT_SOURCE_SET) {
|
||||
message = 'No video or audio devices have been found. Please, connect at least one.';
|
||||
}
|
||||
this.actionService.openDialog(e.name.replace(/_/g, ' '), message, true);
|
||||
this.log.e(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
private generateRandomNickname(): string {
|
||||
return 'OpenVidu_User' + Math.floor(Math.random() * 100);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
#user-settings-container {
|
||||
#pre-join-container {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<div id="call-container">
|
||||
<div id="user-settings-container" *ngIf="!joinSessionClicked && !closeClicked">
|
||||
<ov-user-settings (onJoinClicked)="_onJoinClicked()" (onCloseClicked)="onLeaveSessionClicked()"></ov-user-settings>
|
||||
<div id="pre-join-container" *ngIf="!joinSessionClicked">
|
||||
<ov-pre-join (onJoinClicked)="_onJoinClicked()"></ov-pre-join>
|
||||
<!-- <ov-user-settings (onJoinClicked)="_onJoinClicked()" (onCloseClicked)="onLeaveSessionClicked()"></ov-user-settings> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div id="spinner" *ngIf="joinSessionClicked && !isSessionAlive && !error">
|
||||
|
|
|
@ -58,7 +58,6 @@ export class VideoconferenceComponent implements OnInit, AfterViewInit {
|
|||
webcam: tokens.webcam,
|
||||
screen: tokens.screen
|
||||
};
|
||||
this.joinSessionClicked = true;
|
||||
this.isSessionAlive = true;
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +67,7 @@ export class VideoconferenceComponent implements OnInit, AfterViewInit {
|
|||
@Output() onCloseClicked = new EventEmitter<any>();
|
||||
|
||||
joinSessionClicked: boolean = false;
|
||||
closeClicked: boolean = false;
|
||||
// closeClicked: boolean = false;
|
||||
isSessionAlive: boolean = false;
|
||||
_tokens: { webcam: string; screen: string };
|
||||
error: boolean = false;
|
||||
|
@ -140,10 +139,11 @@ export class VideoconferenceComponent implements OnInit, AfterViewInit {
|
|||
ngOnInit() {}
|
||||
|
||||
async _onJoinClicked() {
|
||||
this.joinSessionClicked = true;
|
||||
this.onJoinClicked.emit();
|
||||
}
|
||||
onLeaveSessionClicked() {
|
||||
this.isSessionAlive = false;
|
||||
this.closeClicked = true;
|
||||
}
|
||||
// onLeaveSessionClicked() {
|
||||
// this.isSessionAlive = false;
|
||||
// this.closeClicked = true;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import { CommonModule } from '@angular/common';
|
|||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
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 { VideoComponent } from './components/video/video.component';
|
||||
import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component';
|
||||
|
@ -58,12 +58,22 @@ import { ParticipantsPanelComponent } from './components/panel/participants-pane
|
|||
import { VideoconferenceComponent } from './components/videoconference/videoconference.component';
|
||||
import { PanelComponent } from './components/panel/panel.component';
|
||||
import { AudioWaveComponent } from './components/audio-wave/audio-wave.component';
|
||||
import { PreJoinComponent } from './components/pre-join/pre-join.component';
|
||||
|
||||
import { ChatPanelDirective, LayoutDirective, PanelDirective, ParticipantPanelItemDirective, ParticipantsPanelDirective, StreamDirective, ToolbarDirective } from './directives/openvidu-angular.directive';
|
||||
import {
|
||||
ChatPanelDirective,
|
||||
LayoutDirective,
|
||||
PanelDirective,
|
||||
ParticipantPanelItemDirective,
|
||||
ParticipantsPanelDirective,
|
||||
StreamDirective,
|
||||
ToolbarDirective
|
||||
} from './directives/openvidu-angular.directive';
|
||||
import { AvatarProfileComponent } from './components/avatar-profile/avatar-profile.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
UserSettingsComponent,
|
||||
// UserSettingsComponent,
|
||||
VideoComponent,
|
||||
ToolbarComponent,
|
||||
ChatPanelComponent,
|
||||
|
@ -77,7 +87,7 @@ import { ChatPanelDirective, LayoutDirective, PanelDirective, ParticipantPanelIt
|
|||
ParticipantPanelItemComponent,
|
||||
ParticipantsPanelComponent,
|
||||
VideoconferenceComponent,
|
||||
AudioWaveComponent,
|
||||
AudioWaveComponent,
|
||||
PanelComponent,
|
||||
ToolbarDirective,
|
||||
PanelDirective,
|
||||
|
@ -85,7 +95,9 @@ import { ChatPanelDirective, LayoutDirective, PanelDirective, ParticipantPanelIt
|
|||
ParticipantsPanelDirective,
|
||||
ParticipantPanelItemDirective,
|
||||
LayoutDirective,
|
||||
StreamDirective
|
||||
StreamDirective,
|
||||
PreJoinComponent,
|
||||
AvatarProfileComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
@ -132,7 +144,7 @@ import { ChatPanelDirective, LayoutDirective, PanelDirective, ParticipantPanelIt
|
|||
],
|
||||
exports: [
|
||||
VideoconferenceComponent,
|
||||
UserSettingsComponent,
|
||||
// UserSettingsComponent,
|
||||
ToolbarComponent,
|
||||
PanelComponent,
|
||||
ParticipantsPanelComponent,
|
||||
|
@ -143,6 +155,7 @@ import { ChatPanelDirective, LayoutDirective, PanelDirective, ParticipantPanelIt
|
|||
StreamComponent,
|
||||
VideoComponent,
|
||||
AudioWaveComponent,
|
||||
PreJoinComponent,
|
||||
ParticipantStreamsPipe,
|
||||
StreamsEnabledPipe,
|
||||
CommonModule,
|
||||
|
|
|
@ -194,7 +194,7 @@ export class DeviceService {
|
|||
}
|
||||
|
||||
clear() {
|
||||
this.OV = new OpenVidu();
|
||||
// this.OV = new OpenVidu();
|
||||
this.devices = [];
|
||||
this.cameras = [];
|
||||
this.microphones = [];
|
||||
|
|
|
@ -22,7 +22,7 @@ export * from './lib/services/storage/storage.service';
|
|||
|
||||
// Components
|
||||
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/panel/panel.component';
|
||||
export * from './lib/components/panel/chat-panel/chat-panel.component';
|
||||
|
@ -33,6 +33,7 @@ export * from './lib/components/layout/layout.component';
|
|||
export * from './lib/components/stream/stream.component';
|
||||
export * from './lib/components/video/video.component';
|
||||
export * from './lib/components/audio-wave/audio-wave.component';
|
||||
export * from './lib/components/pre-join/pre-join.component';
|
||||
|
||||
// Models
|
||||
export * from './lib/models/participant.model';
|
||||
|
|
Loading…
Reference in New Issue