From ea1b84d72b1b496a01954a80cad7eed67bf5e092 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Sat, 14 Jun 2025 13:56:08 +0200 Subject: [PATCH] frontend: add view recording component --- .../src/lib/pages/index.ts | 1 + .../view-recording.component.html | 25 ++++++++ .../view-recording.component.scss | 50 +++++++++++++++ .../view-recording.component.spec.ts | 23 +++++++ .../view-recording.component.ts | 64 +++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.html create mode 100644 frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.scss create mode 100644 frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.spec.ts create mode 100644 frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.ts diff --git a/frontend/projects/shared-meet-components/src/lib/pages/index.ts b/frontend/projects/shared-meet-components/src/lib/pages/index.ts index 9d311c0..788929b 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/index.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/index.ts @@ -12,3 +12,4 @@ export * from './error/error.component'; export * from './login/login.component'; export * from './room-recordings/room-recordings.component'; export * from './video-room/video-room.component'; +export * from './view-recording/view-recording.component'; diff --git a/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.html b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.html new file mode 100644 index 0000000..9d6791c --- /dev/null +++ b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.html @@ -0,0 +1,25 @@ +@if (recording && recordingUrl) { + +
+ +
+ + +

{{ recording.roomId }}

+
+ {{ recording.startDate | date: 'M/d/yy, H:mm' }} +
+ + +
+
+
+
+} diff --git a/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.scss b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.scss new file mode 100644 index 0000000..f6d4610 --- /dev/null +++ b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.scss @@ -0,0 +1,50 @@ +.recording-container { + max-width: 900px; + margin: 20px auto; + padding: 0; +} + +.video-container { + position: relative; + width: 100%; + padding-top: 56.25%; /* 16:9 aspect ratio */ +} + +.video-player { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.title { + font-size: 1.8rem; + font-weight: 600; + margin: 16px 0 8px; +} + +.info-actions { + display: flex; + flex-direction: column; + gap: 8px; +} + +@media (min-width: 600px) { + .info-actions { + flex-direction: row; + justify-content: space-between; + align-items: center; + } +} + +.date { + color: #666; + font-size: 0.95rem; +} + +.actions { + display: flex; + gap: 8px; + align-items: center; +} diff --git a/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.spec.ts b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.spec.ts new file mode 100644 index 0000000..401010d --- /dev/null +++ b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ViewRecordingComponent } from './view-recording.component'; + +describe('ViewRecordingComponent', () => { + let component: ViewRecordingComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ViewRecordingComponent] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewRecordingComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.ts new file mode 100644 index 0000000..35d0cb1 --- /dev/null +++ b/frontend/projects/shared-meet-components/src/lib/pages/view-recording/view-recording.component.ts @@ -0,0 +1,64 @@ +import { DatePipe } from '@angular/common'; +import { Component, OnInit } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDialog } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { ActivatedRoute } from '@angular/router'; +import { ShareRecordingDialogComponent } from '@lib/components'; +import { HttpService } from '@lib/services'; +import { ActionService, MeetRecordingInfo } from 'shared-meet-components'; + +@Component({ + selector: 'app-view-recording', + templateUrl: './view-recording.component.html', + styleUrls: ['./view-recording.component.scss'], + standalone: true, + imports: [MatCardModule, MatButtonModule, MatIconModule, DatePipe] +}) +export class ViewRecordingComponent implements OnInit { + recording: MeetRecordingInfo | undefined; + recordingUrl: string | undefined; + + constructor( + protected httpService: HttpService, + protected actionService: ActionService, + protected route: ActivatedRoute, + protected dialog: MatDialog + ) {} + + async ngOnInit() { + const recordingId = this.route.snapshot.paramMap.get('recording-id'); + const secret = this.route.snapshot.queryParams['secret']; + + this.recording = await this.httpService.getRecording(recordingId!, secret!); + this.playRecording(); + } + + playRecording() { + this.recordingUrl = this.httpService.getRecordingMediaUrl(this.recording!.recordingId); + } + + downloadRecording() { + const link = document.createElement('a'); + link.href = this.recordingUrl!; + link.download = this.recording!.filename || 'openvidu-recording.mp4'; + link.dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + view: window + }) + ); + + // For Firefox it is necessary to delay revoking the ObjectURL + setTimeout(() => link.remove(), 100); + } + + openShareDialog() { + this.dialog.open(ShareRecordingDialogComponent, { + width: '400px', + data: { recordingId: this.recording!.recordingId } + }); + } +}