From 3c97ceac37da59287eafe8f06c6df4725fee78c9 Mon Sep 17 00:00:00 2001
From: csantosm <4a.santos@gmail.com>
Date: Thu, 20 Jan 2022 11:53:56 +0100
Subject: [PATCH] openvidu-components: Added openvidu videoconference
components
---
.../projects/openvidu-angular/package.json | 1 +
.../videoconference.component.css | 23 +++
.../videoconference.component.html | 30 ++++
.../videoconference.component.spec.ts | 25 ++++
.../videoconference.component.ts | 72 ++++++++++
.../src/lib/openvidu-angular.module.ts | 133 +++++++++---------
.../lib/services/rest/rest.service.spec.ts | 16 +++
.../src/lib/services/rest/rest.service.ts | 75 ++++++++++
.../openvidu-angular/src/public-api.ts | 1 +
9 files changed, 307 insertions(+), 69 deletions(-)
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.spec.ts
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.spec.ts
create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.ts
diff --git a/openvidu-components-angular/projects/openvidu-angular/package.json b/openvidu-components-angular/projects/openvidu-angular/package.json
index 55dfcc9b..1b2ff923 100644
--- a/openvidu-components-angular/projects/openvidu-angular/package.json
+++ b/openvidu-components-angular/projects/openvidu-angular/package.json
@@ -9,6 +9,7 @@
"@angular/forms": "^13.0.0",
"@angular/flex-layout": "^13.0.0-beta.36",
"autolinker": "^3.14.3",
+ "buffer": "^6.0.3",
"openvidu-browser": "^2.20.0"
},
"dependencies": {
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css
new file mode 100644
index 00000000..b7bffcca
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css
@@ -0,0 +1,23 @@
+#call-container, #room-container {
+ height: 100%;
+}
+
+#user-settings-container {
+ height: inherit;
+}
+
+.error-icon {
+ color: var(--ov-warn-color);
+}
+
+#spinner {
+ position: absolute;
+ top: 40%;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+ text-align: -webkit-center;
+ text-align: -moz-center;
+ color: var(--ov-primary-color);
+}
\ No newline at end of file
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
new file mode 100644
index 00000000..6c793893
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+ Joining the room ...
+
+
+
+ error
+ {{errorMessage}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.spec.ts
new file mode 100644
index 00000000..faa9c113
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { VideoconferenceComponent } from './videoconference.component';
+
+describe('VideoconferenceComponent', () => {
+ let component: VideoconferenceComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ VideoconferenceComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(VideoconferenceComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
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
new file mode 100644
index 00000000..23050514
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts
@@ -0,0 +1,72 @@
+import { Component, Input, OnInit, Output } from '@angular/core';
+import { RestService } from '../../services/rest/rest.service';
+
+@Component({
+ selector: 'ov-videoconference',
+ templateUrl: './videoconference.component.html',
+ styleUrls: ['./videoconference.component.css']
+})
+export class VideoconferenceComponent implements OnInit {
+ @Input() sessionName: string;
+ @Input() userName: string;
+ @Input() openviduServerUrl: string;
+ @Input() openviduSecret: string;
+ @Input() tokens: string[];
+
+ joinSessionClicked: boolean = false;
+ closeClicked: boolean = false;
+ isSessionAlive: boolean = false;
+ _tokens: { webcam: string; screen: string };
+ error: boolean = false;
+ errorMessage: string = '';
+
+ constructor(private restService: RestService) {}
+
+ ngOnInit() {}
+
+ async onJoinClicked() {
+
+ if (!this.tokens || this.tokens?.length === 0) {
+ //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?.length < 2) {
+ // 1 token received
+ this._tokens = {
+ webcam: this.tokens[0],
+ screen: await this.restService.getToken(this.sessionName, this.openviduServerUrl, this.openviduSecret)
+ };
+ } else {
+ // 2 tokens received.
+ this._tokens = {
+ webcam: this.tokens[0],
+ screen: this.tokens[1]
+ };
+ }
+ this.joinSessionClicked = true;
+ this.isSessionAlive = true;
+ }
+ onLeaveSessionClicked() {
+ this.isSessionAlive = false;
+ this.closeClicked = true;
+ }
+
+ onMicClicked() {}
+
+ onCamClicked() {}
+
+ onScreenShareClicked() {}
+
+ onSpeakerLayoutClicked() {}
+}
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 92eecb8b..f2b2d23a 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
@@ -56,31 +56,33 @@ 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 { ParticipantPanelComponent } from './components/participants-panel/participant-panel/participant-panel.component';
+import { VideoconferenceComponent } from './components/videoconference/videoconference.component';
@NgModule({
- declarations: [
- UserSettingsComponent,
- VideoComponent,
- ToolbarComponent,
- ChatComponent,
- RoomComponent,
- LayoutComponent,
- ParticipantComponent,
- DialogTemplateComponent,
- LinkifyPipe,
- TooltipListPipe,
- ParticipantConnectionsPipe,
- ConnectionsEnabledPipe,
- NicknamePipe,
- ParticipantItemComponent,
- ParticipantPanelComponent
- ],
- imports: [
- CommonModule,
- HttpClientModule,
- FormsModule,
+ declarations: [
+ UserSettingsComponent,
+ VideoComponent,
+ ToolbarComponent,
+ ChatComponent,
+ RoomComponent,
+ LayoutComponent,
+ ParticipantComponent,
+ DialogTemplateComponent,
+ LinkifyPipe,
+ TooltipListPipe,
+ ParticipantConnectionsPipe,
+ ConnectionsEnabledPipe,
+ NicknamePipe,
+ ParticipantItemComponent,
+ ParticipantPanelComponent,
+ VideoconferenceComponent
+ ],
+ imports: [
+ CommonModule,
+ HttpClientModule,
+ FormsModule,
ReactiveFormsModule,
- RouterModule.forRoot([]),
+ RouterModule.forRoot([]),
MatButtonModule,
MatCardModule,
MatToolbarModule,
@@ -99,53 +101,46 @@ import { ParticipantPanelComponent } from './components/participants-panel/parti
MatSnackBarModule,
FlexLayoutModule,
MatMenuModule,
- MatDividerModule,
- MatListModule
- ],
- providers: [
- ActionService,
- CdkOverlayContainer,
+ MatDividerModule,
+ MatListModule
+ ],
+ providers: [
+ ActionService,
+ CdkOverlayContainer,
{ provide: OverlayContainer, useClass: CdkOverlayContainer },
- ChatService,
- SidenavMenuService,
- DeviceService,
- DocumentService,
- LayoutService,
- LoggerService,
- PlatformService,
- ParticipantService,
- StorageService,
- TokenService,
- WebrtcService
-
- ],
- exports: [
- UserSettingsComponent,
- ToolbarComponent,
- ChatComponent,
- RoomComponent,
- LayoutComponent,
- ParticipantComponent,
- VideoComponent,
- ParticipantConnectionsPipe,
- CommonModule
- ],
- entryComponents: [
- DialogTemplateComponent
- ]
+ ChatService,
+ SidenavMenuService,
+ DeviceService,
+ DocumentService,
+ LayoutService,
+ LoggerService,
+ PlatformService,
+ ParticipantService,
+ StorageService,
+ TokenService,
+ WebrtcService
+ ],
+ exports: [
+ VideoconferenceComponent,
+ UserSettingsComponent,
+ ToolbarComponent,
+ ChatComponent,
+ RoomComponent,
+ LayoutComponent,
+ ParticipantComponent,
+ VideoComponent,
+ ParticipantConnectionsPipe,
+ CommonModule
+ ],
+ entryComponents: [DialogTemplateComponent]
})
-
-
export class OpenviduAngularModule {
- static forRoot(environment): ModuleWithProviders {
-
- // console.log(`${library.name} config: ${environment}`);
- const libConfig: LibConfig = { environment };
- return {
- ngModule: OpenviduAngularModule,
- providers: [LibraryConfigService , {provide: 'LIB_CONFIG', useValue: libConfig}]
- };
- }
-
-
- }
+ static forRoot(environment): ModuleWithProviders {
+ // console.log(`${library.name} config: ${environment}`);
+ const libConfig: LibConfig = { environment };
+ return {
+ ngModule: OpenviduAngularModule,
+ providers: [LibraryConfigService, { provide: 'LIB_CONFIG', useValue: libConfig }]
+ };
+ }
+}
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.spec.ts
new file mode 100644
index 00000000..c0a594f3
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { RestService } from './rest.service';
+
+describe('RestService', () => {
+ let service: RestService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(RestService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.ts
new file mode 100644
index 00000000..8a11a50f
--- /dev/null
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/rest/rest.service.ts
@@ -0,0 +1,75 @@
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { catchError, throwError } from 'rxjs';
+import { Buffer} from 'buffer';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class RestService {
+ constructor(private http: HttpClient) {}
+
+ async getToken(sessionId: string, openviduServerUrl: string, openviduSecret: string): Promise {
+ if (!!openviduServerUrl && !!openviduSecret) {
+ const _sessionId = await this.createSession(sessionId, openviduServerUrl, openviduSecret);
+ return await this.createToken(_sessionId, openviduServerUrl, openviduSecret);
+ } else {
+ return Promise.reject(`Error requesting a token to ${openviduServerUrl} with session id: ${sessionId}`);
+ }
+ }
+
+ private createSession(sessionId: string, openviduServerUrl: string, openviduSecret: string): Promise {
+ return new Promise((resolve, reject) => {
+ const body = JSON.stringify({ customSessionId: sessionId });
+ const options = {
+ headers: new HttpHeaders({
+ Authorization: 'Basic ' + this.btoa('OPENVIDUAPP:' + openviduSecret),
+ 'Content-Type': 'application/json'
+ })
+ };
+ return this.http
+ .post(openviduServerUrl + '/openvidu/api/sessions', body, options)
+ .pipe(
+ catchError((error) => {
+ if (error.status === 409) {
+ resolve(sessionId);
+ }
+ if (error.statusText === 'Unknown Error') {
+ reject({ status: 401, message: 'ERR_CERT_AUTHORITY_INVALID' });
+ }
+ return throwError(() => new Error(error));
+ })
+ )
+ .subscribe((response) => {
+ resolve(response.id);
+ });
+ });
+ }
+
+ private createToken(sessionId: string, openviduServerUrl: string, openviduSecret: string): Promise {
+ return new Promise((resolve, reject) => {
+ const body = JSON.stringify({});
+ const options = {
+ headers: new HttpHeaders({
+ Authorization: 'Basic ' + this.btoa('OPENVIDUAPP:' + openviduSecret),
+ 'Content-Type': 'application/json'
+ })
+ };
+ return this.http
+ .post(openviduServerUrl + '/openvidu/api/sessions/' + sessionId + '/connection', body, options)
+ .pipe(
+ catchError((error) => {
+ reject(error);
+ return throwError(() => new Error(error));
+ })
+ )
+ .subscribe((response) => {
+ resolve(response.token);
+ });
+ });
+ }
+
+ private btoa(str: string): string {
+ return Buffer.from(str).toString('base64');
+ }
+}
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 311c36b3..1d037218 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts
@@ -21,6 +21,7 @@ export * from './lib/services/cdk-overlay/cdk-overlay.service';
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/toolbar/toolbar.component';
export * from './lib/components/chat/chat.component';