114 lines
3.8 KiB
TypeScript

import { animate, style, transition, trigger } from '@angular/animations';
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { lastValueFrom } from 'rxjs';
import {
DataPacket_Kind,
DataPublishOptions,
ParticipantService,
RemoteParticipant,
Room,
RoomEvent,
OpenViduAngularModule,
ApiDirectiveModule,
OpenViduAngularDirectiveModule
} from 'openvidu-angular';
import { ParticipantAppModel } from './models/participant-app.model';
import { environment } from 'src/environments/environment';
import { MatIcon } from '@angular/material/icon';
import { MatIconButton } from '@angular/material/button';
enum DataTopicApp {
HAND_TOGGLE = 'handToggle'
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('inOutHandAnimation', [
transition(':enter', [
style({ opacity: 0, transform: 'translateY(-100%)' }),
animate('300ms ease-in-out', style({ opacity: 1, transform: 'translateY(0)' }))
]),
transition(':leave', [
style({ opacity: 1, transform: 'translateY(0)' }),
animate('300ms ease-in-out', style({ opacity: 0, transform: 'translateY(-100%)' }))
])
])
],
standalone: true,
imports: [OpenViduAngularModule, ApiDirectiveModule, OpenViduAngularDirectiveModule, MatIconButton, MatIcon]
})
export class AppComponent {
// The URL of the application server.
APPLICATION_SERVER_URL = '';
LIVEKIT_URL = environment.livekitUrl;
// The token used to connect to the OpenVidu session.
token!: string;
// Whether the local participant has raised their hand.
hasHandRaised: boolean = false;
// The name of the OpenVidu room.
private roomName = 'openvidu-toggle-hand';
constructor(private httpClient: HttpClient, private participantService: ParticipantService) {}
// Requests a token from the application server for the given participant name.
async onTokenRequested(participantName: string) {
const { token } = await this.getToken(this.roomName, participantName);
this.token = token;
}
// Handles the reception of a remote hand-raising event.
handleRemoteHand(room: Room) {
// Subscribe to hand toggling events from other participants
room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant?: RemoteParticipant, _?: DataPacket_Kind, topic?: string) => {
if (topic === DataTopicApp.HAND_TOGGLE) {
const p = this.participantService.getRemoteParticipantBySid(participant.sid);
if (p) {
(<ParticipantAppModel>p).toggleHandRaised();
}
this.participantService.updateRemoteParticipants();
}
});
}
// Handles the local hand-raising event.
async handleLocalHand() {
// Get local participant with ParticipantService
const participant = <ParticipantAppModel>this.participantService.getLocalParticipant();
// Toggle the participant hand with the method we wil add in our ParticipantAppModel
participant.toggleHandRaised();
// Refresh the local participant object for others component and services
this.participantService.updateLocalParticipant();
// Send a signal with the new value to others participant using the openvidu-browser signal
const strData = JSON.stringify({});
const data: Uint8Array = new TextEncoder().encode(strData);
const options: DataPublishOptions = { topic: DataTopicApp.HAND_TOGGLE };
await this.participantService.publishData(data, options);
}
// Requests a token from the application server for the given room and participant names.
getToken(roomName: string, participantName: string): Promise<any> {
try {
return lastValueFrom(this.httpClient.post<any>(this.APPLICATION_SERVER_URL + 'token', { roomName, participantName }));
} catch (error: any) {
if (error.status === 404) {
throw { status: error.status, message: 'Cannot connect with backend. ' + error.url + ' not found' };
}
throw error;
}
}
}