From b8fac1fc0c1de1194c3632d1d9e24371b4590e31 Mon Sep 17 00:00:00 2001 From: Kent Anderson Date: Wed, 20 Mar 2024 23:45:05 -0500 Subject: [PATCH] feat-1332 code cleanup --- .../frame-selector.component.ts | 59 ++++++------ .../thumbnail-manager.component.ts | 89 +++++++++---------- .../core/controllers/api/videos/thumbnails.ts | 9 +- 3 files changed, 75 insertions(+), 82 deletions(-) diff --git a/client/src/app/+videos/+video-edit/shared/thumbnail-manager/frame-selector.component.ts b/client/src/app/+videos/+video-edit/shared/thumbnail-manager/frame-selector.component.ts index aefb490b6..a814bc3d0 100644 --- a/client/src/app/+videos/+video-edit/shared/thumbnail-manager/frame-selector.component.ts +++ b/client/src/app/+videos/+video-edit/shared/thumbnail-manager/frame-selector.component.ts @@ -1,5 +1,5 @@ -import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation, Output, EventEmitter } from '@angular/core'; -import videojs from 'video.js'; +import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild, Output, EventEmitter, ViewEncapsulation } from '@angular/core' +import videojs from 'video.js' @Component({ selector: 'my-frame-selector', @@ -11,31 +11,28 @@ import videojs from 'video.js'; `, - styleUrls: ['./frame-selector.component.scss'], + styleUrls: [ './frame-selector.component.scss' ], + /* eslint-disable @angular-eslint/use-component-view-encapsulation */ encapsulation: ViewEncapsulation.None, standalone: true }) export class FrameSelectorComponent implements OnInit, OnDestroy { - @ViewChild('frameSelector', { static: true }) target: ElementRef; + @ViewChild('frameSelector', { static: true }) target: ElementRef @Input() source: string - @Output() timeChanged = new EventEmitter(); + @Output() timeChanged = new EventEmitter() - private player: videojs.Player; - - constructor( - ) { } - - async ngOnInit() { + private player: videojs.Player + ngOnInit () { // Configuring the player, optimizing for frame selection - let options = { - sources: [{ + const options = { + sources: [ { src: this.source - }], + } ], controlBar: { fullscreenToggle: false }, @@ -43,40 +40,40 @@ export class FrameSelectorComponent implements OnInit, OnDestroy { controls: true, muted: true, fluid: true, - aspectRatio: "16:9", + aspectRatio: '16:9', playsinline: true, userActions: { hotkeys: (event: videojs.KeyboardEvent) => { // Space -pause/play - if (event.key === " ") { + if (event.key === ' ') { if (this.player.paused()) { - this.player.play(); + this.player.play() } else { - this.player.pause(); + this.player.pause() } } // Allow more accurate frame selection - if (event.key === "ArrowRight") { + if (event.key === 'ArrowRight') { // Stop the video this.player.pause() // Forward - let step = 0.5 + const step = 0.5 this.player.currentTime(this.player.currentTime() + step) } - if (event.key === "ArrowLeft") { + if (event.key === 'ArrowLeft') { // Stop the video - this.player.pause(); + this.player.pause() // Back - let step = 0.5 + const step = 0.5 this.player.currentTime(this.player.currentTime() - step) } } @@ -84,30 +81,30 @@ export class FrameSelectorComponent implements OnInit, OnDestroy { } // Create the player - this.player = await videojs(this.target.nativeElement, options) + this.player = videojs(this.target.nativeElement, options) - // Awaiting then calling instead of call back. Makes it easier to reference + // Waiting then calling instead of call back. Makes it easier to reference // the event emitter this.onPlayerReady() } // Dispose the player OnDestroy - ngOnDestroy() { + ngOnDestroy () { if (this.player) { - this.player.dispose(); + this.player.dispose() } } - onTimeChanged(value: number) { - this.timeChanged.emit(value); + onTimeChanged (value: number) { + this.timeChanged.emit(value) } - onPlayerReady() { + onPlayerReady () { this.player.on('timeupdate', () => { // Event listener that will emit the current time this.onTimeChanged(this.player.currentTime()) }) } -} \ No newline at end of file +} diff --git a/client/src/app/+videos/+video-edit/shared/thumbnail-manager/thumbnail-manager.component.ts b/client/src/app/+videos/+video-edit/shared/thumbnail-manager/thumbnail-manager.component.ts index ddb3f2fac..28718c57a 100644 --- a/client/src/app/+videos/+video-edit/shared/thumbnail-manager/thumbnail-manager.component.ts +++ b/client/src/app/+videos/+video-edit/shared/thumbnail-manager/thumbnail-manager.component.ts @@ -1,5 +1,5 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' -import { CommonModule } from '@angular/common'; +import { CommonModule } from '@angular/common' import { imageToDataURL } from '../../../../../root-helpers/images' import { BytesPipe } from '../../../../shared/shared-main/angular/bytes.pipe' @@ -13,11 +13,10 @@ import { } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { - AuthService, ConfirmService, Notifier, RestExtractor, - ServerService, + ServerService } from '../../../../core' import { VideoDetails } from '../../../../shared/shared-main/video/video-details.model' import { VideoFileTokenService } from '../../../../shared/shared-main/video/video-file-token.service' @@ -29,12 +28,12 @@ import { ServerErrorCode } from '@peertube/peertube-models' import { videoRequiresFileToken } from '../../../../../root-helpers/video' -import { FrameSelectorComponent } from './frame-selector.component'; -import { ReactiveFileComponent } from '@app/shared/shared-forms/reactive-file.component'; +import { FrameSelectorComponent } from './frame-selector.component' +import { ReactiveFileComponent } from '@app/shared/shared-forms/reactive-file.component' @Component({ selector: 'my-thumbnail-manager', - styleUrls: ['./thumbnail-manager.component.scss'], + styleUrls: [ './thumbnail-manager.component.scss' ], templateUrl: './thumbnail-manager.component.html', standalone: true, imports: [ CommonModule, FrameSelectorComponent, ReactiveFileComponent ], @@ -48,8 +47,8 @@ import { ReactiveFileComponent } from '@app/shared/shared-forms/reactive-file.co }) export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { - previewWidth = "360px" - previewHeight = "200px" + previewWidth = '360px' + previewHeight = '200px' imageSrc: string allowedExtensionsMessage = '' @@ -60,16 +59,16 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { file: Blob // State Toggle (Upload, Select Frame) - selectingFromVideo: boolean = false + selectingFromVideo = false source: string - currentTime: number = 0 + currentTime = 0 videoId: string videoDetails: VideoDetails - constructor( + constructor ( private confirmService: ConfirmService, private notifier: Notifier, private restExtractor: RestExtractor, @@ -82,31 +81,30 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { this.maxSizeText = $localize`max size` } - - // Section - Upload - get videoImageExtensions() { + // Section - Upload + get videoImageExtensions () { return this.serverConfig.video.image.extensions } - get maxVideoImageSize() { + get maxVideoImageSize () { return this.serverConfig.video.image.size.max } - get maxVideoImageSizeInBytes() { + get maxVideoImageSizeInBytes () { return this.bytesPipe.transform(this.maxVideoImageSize) } - getReactiveFileButtonTooltip() { + getReactiveFileButtonTooltip () { return $localize`(extensions: ${this.videoImageExtensions}, ${this.maxSizeText}\: ${this.maxVideoImageSizeInBytes})` } - ngOnInit() { + ngOnInit () { this.serverConfig = this.serverService.getHTMLConfig() this.allowedExtensionsMessage = this.videoImageExtensions.join(', ') } - onFileChanged(file: Blob) { + onFileChanged (file: Blob) { this.file = file this.propagateChange(this.file) @@ -115,20 +113,20 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { propagateChange = (_: any) => { /* empty */ } - writeValue(file: any) { + writeValue (file: any) { this.file = file this.updatePreview() } - registerOnChange(fn: (_: any) => void) { + registerOnChange (fn: (_: any) => void) { this.propagateChange = fn } - registerOnTouched() { + registerOnTouched () { // Unused } - private updatePreview() { + private updatePreview () { if (this.file) { imageToDataURL(this.file).then(result => this.imageSrc = result) } @@ -137,7 +135,7 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { // Section - Select From Frame - selectFromVideo() { + selectFromVideo () { this.selectingFromVideo = true @@ -153,33 +151,30 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { }) } - resetSelectFromVideo() { + resetSelectFromVideo () { this.selectingFromVideo = false } - selectFrame() { + selectFrame () { this.selectingFromVideo = false - this.videoService.setThumbnailAtTimecode( - this.videoDetails.id.toString(), - this.currentTime.toString()).subscribe((response) => { - + this.videoService.setThumbnailAtTimecode(this.videoDetails.id.toString(), this.currentTime.toString()) + .subscribe((response) => { this.imageSrc = response - }) } - getCurrentTime() { + getCurrentTime () { return this.currentTime } - setCurrentTime(value: number) { - this.currentTime = value; + setCurrentTime (value: number) { + this.currentTime = value } - private loadVideo(options: { + private loadVideo (options: { videoId: string }) { const { videoId } = options @@ -191,22 +186,22 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { return this.videoFileTokenService.getVideoFileToken({ videoUUID: video.uuid }) .pipe(map((token) => ({ video, videoFileToken: token.token }))) - })).subscribe({ + + })) + .subscribe({ next: ({ video, videoFileToken }) => { this.onVideoFetched({ video, videoFileToken - }).catch(err => { - this.handleGlobalError(err) }) }, - error: async err => { + error: err => { this.handleRequestError(err) } }) } - private async onVideoFetched(options: { + private onVideoFetched (options: { video: VideoDetails videoFileToken: string }) { @@ -217,10 +212,10 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { this.videoDetails = video - let videoFiles = video.getFiles() + const videoFiles = video.getFiles() if (videoFiles == null) { - if (videoFiles.length == 0) { + if (videoFiles.length === 0) { return } } @@ -228,10 +223,10 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { let url: string = videoFiles[0].fileUrl if (videoFileToken != null) { - url = addQueryParams(url, { videoFileToken: videoFileToken }) + url = addQueryParams(url, { videoFileToken }) } - this.source = url + this.source = url console.log(url) } @@ -239,14 +234,14 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { // Section - Helpers - private handleGlobalError(err: any) { + private handleGlobalError (err: any) { const errorMessage: string = typeof err === 'string' ? err : err.message if (!errorMessage) return this.notifier.error(errorMessage) } - private async handleRequestError(err: any) { + private async handleRequestError (err: any) { const errorBody = err.body as PeerTubeProblemDocument if (errorBody?.code === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && errorBody.originUrl) { @@ -270,4 +265,4 @@ export class ThumbnailManagerComponent implements OnInit, ControlValueAccessor { } // End Section - Helpers -} \ No newline at end of file +} diff --git a/server/core/controllers/api/videos/thumbnails.ts b/server/core/controllers/api/videos/thumbnails.ts index c7c44ae53..91ef2ffa8 100644 --- a/server/core/controllers/api/videos/thumbnails.ts +++ b/server/core/controllers/api/videos/thumbnails.ts @@ -3,11 +3,12 @@ import { VideoModel } from '@server/models/video/video.js' import { generateLocalVideoMiniature } from '../../../lib/thumbnail.js' import { MThumbnail, MVideoWithAllFiles } from '@server/types/models/index.js' import { ThumbnailType } from '@peertube/peertube-models' +import { asyncMiddleware } from '@server/middlewares/index.js' const thumbnailRouter = express.Router() thumbnailRouter.put('/:id/thumbnail/:timecode', - setThumbnailAtTimecode + asyncMiddleware(setThumbnailAtTimecode) ) export { @@ -34,15 +35,15 @@ async function setThumbnailAtTimecode (req: express.Request, res: express.Respon let url: string - thumbnails.forEach((thumbnail) => { + await Promise.all(thumbnails.map(async (thumbnail) => { - thumbnail.save() + await thumbnail.save() if (thumbnail.type === ThumbnailType.PREVIEW) { url = thumbnail.getOriginFileUrl(video) } - }) + })) return res.json(url) }