Update Angular tutorial to use signals

This commit is contained in:
juancarmore 2024-05-31 14:12:45 +02:00
parent 3b69def2ef
commit b67a8f0e9d
6 changed files with 47 additions and 66 deletions

View File

@ -1,4 +1,4 @@
@if (!room) {
@if (!room()) {
<div id="join">
<div id="join-dialog">
<h2>Join a Video Room</h2>
@ -22,14 +22,14 @@
<button class="btn btn-danger" id="leave-room-button" (click)="leaveRoom()">Leave Room</button>
</div>
<div id="layout-container">
@if (localTrack) {
@if (localTrack()) {
<video-component
[track]="localTrack"
[track]="localTrack()!"
[participantIdentity]="roomForm.value.participantName!"
[local]="true"
></video-component>
}
@for (remoteTrack of remoteTracksMap.values(); track remoteTrack.trackPublication.trackSid) {
@for (remoteTrack of remoteTracksMap().values(); track remoteTrack.trackPublication.trackSid) {
@if (remoteTrack.trackPublication.kind === 'video') {
<video-component
[track]="remoteTrack.trackPublication.videoTrack!"

View File

@ -1,4 +1,4 @@
import { Component, HostListener, OnDestroy } from '@angular/core';
import { Component, HostListener, OnDestroy, signal } from '@angular/core';
import { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';
import {
LocalVideoTrack,
@ -36,9 +36,9 @@ export class AppComponent implements OnDestroy {
participantName: new FormControl('Participant' + Math.floor(Math.random() * 100), Validators.required),
});
room?: Room;
localTrack?: LocalVideoTrack;
remoteTracksMap: Map<string, TrackInfo> = new Map();
room = signal<Room | undefined>(undefined);
localTrack = signal<LocalVideoTrack | undefined>(undefined);
remoteTracksMap = signal<Map<string, TrackInfo>>(new Map());
constructor(private httpClient: HttpClient) {
this.configureUrls();
@ -66,23 +66,30 @@ export class AppComponent implements OnDestroy {
async joinRoom() {
// Initialize a new Room object
this.room = new Room();
const room = new Room();
this.room.set(room);
// Specify the actions when events take place in the room
// On every new Track received...
this.room.on(
room.on(
RoomEvent.TrackSubscribed,
(_track: RemoteTrack, publication: RemoteTrackPublication, participant: RemoteParticipant) => {
this.remoteTracksMap.set(publication.trackSid, {
trackPublication: publication,
participantIdentity: participant.identity,
this.remoteTracksMap.update((map) => {
map.set(publication.trackSid, {
trackPublication: publication,
participantIdentity: participant.identity,
});
return map;
});
}
);
// On every new Track destroyed...
this.room.on(RoomEvent.TrackUnsubscribed, (_track: RemoteTrack, publication: RemoteTrackPublication) => {
this.remoteTracksMap.delete(publication.trackSid);
room.on(RoomEvent.TrackUnsubscribed, (_track: RemoteTrack, publication: RemoteTrackPublication) => {
this.remoteTracksMap.update((map) => {
map.delete(publication.trackSid);
return map;
});
});
try {
@ -94,11 +101,11 @@ export class AppComponent implements OnDestroy {
const token = await this.getToken(roomName, participantName);
// Connect to the room with the LiveKit URL and the token
await this.room.connect(LIVEKIT_URL, token);
await room.connect(LIVEKIT_URL, token);
// Publish your camera and microphone
await this.room.localParticipant.enableCameraAndMicrophone();
this.localTrack = this.room.localParticipant.videoTrackPublications.values().next().value.videoTrack;
await room.localParticipant.enableCameraAndMicrophone();
this.localTrack.set(room.localParticipant.videoTrackPublications.values().next().value.videoTrack);
} catch (error: any) {
console.log(
'There was an error connecting to the room:',
@ -110,12 +117,12 @@ export class AppComponent implements OnDestroy {
async leaveRoom() {
// Leave the room by calling 'disconnect' method over the Room object
await this.room?.disconnect();
await this.room()?.disconnect();
// Reset all variables
delete this.room;
delete this.localTrack;
this.remoteTracksMap.clear();
this.room.set(undefined);
this.localTrack.set(undefined);
this.remoteTracksMap.set(new Map());
}
@HostListener('window:beforeunload')

View File

@ -1 +1 @@
<audio #audioElement [id]="track?.sid"></audio>
<audio #audioElement [id]="track().sid"></audio>

View File

@ -1,4 +1,4 @@
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnDestroy, input, viewChild } from '@angular/core';
import { LocalAudioTrack, RemoteAudioTrack } from 'livekit-client';
@Component({
@ -9,30 +9,17 @@ import { LocalAudioTrack, RemoteAudioTrack } from 'livekit-client';
styleUrl: './audio.component.css',
})
export class AudioComponent implements AfterViewInit, OnDestroy {
@ViewChild('audioElement') audioElement?: ElementRef<HTMLAudioElement>;
audioElement = viewChild<ElementRef<HTMLAudioElement>>('audioElement');
private _track?: RemoteAudioTrack | LocalAudioTrack;
@Input()
set track(track: RemoteAudioTrack | LocalAudioTrack) {
this._track = track;
if (this.audioElement) {
this._track.attach(this.audioElement.nativeElement);
}
}
get track(): RemoteAudioTrack | LocalAudioTrack | undefined {
return this._track;
}
track = input.required<LocalAudioTrack | RemoteAudioTrack>();
ngAfterViewInit() {
if (this._track && this.audioElement) {
this._track.attach(this.audioElement.nativeElement);
if (this.audioElement()) {
this.track().attach(this.audioElement()!.nativeElement);
}
}
ngOnDestroy() {
this._track?.detach();
this.track().detach();
}
}

View File

@ -1,6 +1,6 @@
<div [id]="'camera-' + participantIdentity" class="video-container">
<div [id]="'camera-' + participantIdentity()" class="video-container">
<div class="participant-data">
<p>{{ participantIdentity + (local ? " (You)" : "") }}</p>
<p>{{ participantIdentity() + (local() ? " (You)" : "") }}</p>
</div>
<video #videoElement [id]="track?.sid"></video>
<video #videoElement [id]="track().sid"></video>
</div>

View File

@ -1,4 +1,4 @@
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnDestroy, input, viewChild } from '@angular/core';
import { LocalVideoTrack, RemoteVideoTrack } from 'livekit-client';
@Component({
@ -9,32 +9,19 @@ import { LocalVideoTrack, RemoteVideoTrack } from 'livekit-client';
styleUrl: './video.component.css',
})
export class VideoComponent implements AfterViewInit, OnDestroy {
@ViewChild('videoElement') videoElement?: ElementRef<HTMLVideoElement>;
videoElement = viewChild<ElementRef<HTMLVideoElement>>('videoElement');
private _track?: LocalVideoTrack | RemoteVideoTrack;
@Input() participantIdentity?: string;
@Input() local = false;
@Input()
set track(track: LocalVideoTrack | RemoteVideoTrack) {
this._track = track;
if (this.videoElement) {
this._track.attach(this.videoElement.nativeElement);
}
}
get track(): LocalVideoTrack | RemoteVideoTrack | undefined {
return this._track;
}
track = input.required<LocalVideoTrack | RemoteVideoTrack>();
participantIdentity = input.required<string>();
local = input(false);
ngAfterViewInit() {
if (this._track && this.videoElement) {
this._track.attach(this.videoElement.nativeElement);
if (this.videoElement()) {
this.track().attach(this.videoElement()!.nativeElement);
}
}
ngOnDestroy() {
this._track?.detach();
this.track().detach();
}
}