diff --git a/client/src/app/+admin/follows/follows.component.html b/client/src/app/+admin/follows/follows.component.html index 1baba5a4d821b65fd963c14877a4200e96403172..d3d7486229f4eca5cd05d315e38aecabb474a938 100644 --- a/client/src/app/+admin/follows/follows.component.html +++ b/client/src/app/+admin/follows/follows.component.html @@ -10,6 +10,4 @@ </tabset> </div> - - <router-outlet></router-outlet> diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index 65714fd053e542b4541851e83c5298c638de615b..553ad8af6f8550cdf7dff72f643ffaf161b614ad 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -35,6 +35,10 @@ export class ServerService { } }, video: { + image: { + size: { max: 0 }, + extensions: [] + }, file: { extensions: [] } diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts index 500b5bc5f1bcfccc4c6ae67df3fb10e63cc57e76..34a237a120116ff770f815fd1bf092884a3804d6 100644 --- a/client/src/app/shared/forms/form-validators/video.ts +++ b/client/src/app/shared/forms/form-validators/video.ts @@ -31,6 +31,11 @@ export const VIDEO_LANGUAGE = { MESSAGES: {} } +export const VIDEO_IMAGE = { + VALIDATORS: [ ], + MESSAGES: {} +} + export const VIDEO_CHANNEL = { VALIDATORS: [ Validators.required ], MESSAGES: { diff --git a/client/src/app/shared/forms/markdown-textarea.component.html b/client/src/app/shared/forms/markdown-textarea.component.html index d2d4cf95cb3580f8b5522ffa9863a1560d261dae..e8c5ded5b0c64d87da97e389bad971d79f48d480 100644 --- a/client/src/app/shared/forms/markdown-textarea.component.html +++ b/client/src/app/shared/forms/markdown-textarea.component.html @@ -5,7 +5,7 @@ id="description" name="description"> </textarea> - <tabset *ngIf="arePreviewsDisplayed()" #staticTabs class="previews"> + <tabset *ngIf="arePreviewsDisplayed()" class="previews"> <tab *ngIf="truncate !== undefined" heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab> <tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab> </tabset> diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts index e6a6970983a0a8a45f9603c49a21d9ef925bc8e2..e2e4c5b36bb3ea2ccb591c7c7fa8b5d036e6d9f1 100644 --- a/client/src/app/shared/misc/utils.ts +++ b/client/src/app/shared/misc/utils.ts @@ -67,6 +67,27 @@ function isInMobileView () { return window.innerWidth < 500 } +// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34 +function objectToFormData (obj: any, form?: FormData, namespace?: string) { + let fd = form || new FormData() + let formKey + + for (let key of Object.keys(obj)) { + if (namespace) formKey = `${namespace}[${key}]` + else formKey = key + + if (obj[key] === undefined) continue + + if (typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { + objectToFormData(obj[ key ], fd, key) + } else { + fd.append(formKey, obj[ key ]) + } + } + + return fd +} + export { viewportHeight, getParameterByName, @@ -75,5 +96,6 @@ export { dateToHuman, isInSmallView, isInMobileView, - immutableAssign + immutableAssign, + objectToFormData } diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 330a0ba84a4d3c5240900b0840a0cfe94e629777..2a942647947b72b3ed5d184fbfbae5f7e4ba3525 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -40,10 +40,10 @@ import { VideoService } from './video/video.service' BsDropdownModule.forRoot(), ModalModule.forRoot(), + TabsModule.forRoot(), PrimeSharedModule, - NgPipesModule, - TabsModule.forRoot() + NgPipesModule ], declarations: [ @@ -69,6 +69,7 @@ import { VideoService } from './video/video.service' BsDropdownModule, ModalModule, + TabsModule, PrimeSharedModule, BytesPipe, KeysPipe, diff --git a/client/src/app/shared/video/video-edit.model.ts b/client/src/app/shared/video/video-edit.model.ts index b1c77221783b11609b19891b32120769855e4069..c39252f46fffa527b81381ef206aa273fb62bcdd 100644 --- a/client/src/app/shared/video/video-edit.model.ts +++ b/client/src/app/shared/video/video-edit.model.ts @@ -12,6 +12,10 @@ export class VideoEdit { commentsEnabled: boolean channel: number privacy: VideoPrivacy + thumbnailfile?: any + previewfile?: any + thumbnailUrl: string + previewUrl: string uuid?: string id?: number @@ -29,6 +33,8 @@ export class VideoEdit { this.commentsEnabled = videoDetails.commentsEnabled this.channel = videoDetails.channel.id this.privacy = videoDetails.privacy + this.thumbnailUrl = videoDetails.thumbnailUrl + this.previewUrl = videoDetails.previewUrl } } diff --git a/client/src/app/shared/video/video-thumbnail.component.html b/client/src/app/shared/video/video-thumbnail.component.html index 8acfb3c41b3723266f0b163e1fa1fb642658f6b7..4604d10e250f4b6490facd14a2dce13c3880a043 100644 --- a/client/src/app/shared/video/video-thumbnail.component.html +++ b/client/src/app/shared/video/video-thumbnail.component.html @@ -2,7 +2,7 @@ [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name" class="video-thumbnail" > -<img [attr.src]="getImageUrl()" alt="video thumbnail" [ngClass]="{ 'blur-filter': nsfw }" /> +<img [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" /> <div class="video-thumbnail-overlay"> {{ video.durationLabel }} diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index 01d32176b0d61b77314aa6b3896837d9d23580f4..2e7138cd1fe187a6b16ad9249ff74aa554b600de 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts @@ -18,6 +18,7 @@ import { SortField } from './sort-field.type' import { VideoDetails } from './video-details.model' import { VideoEdit } from './video-edit.model' import { Video } from './video.model' +import { objectToFormData } from '@app/shared/misc/utils' @Injectable() export class VideoService { @@ -46,10 +47,10 @@ export class VideoService { } updateVideo (video: VideoEdit) { - const language = video.language || null - const licence = video.licence || null - const category = video.category || null - const description = video.description || null + const language = video.language || undefined + const licence = video.licence || undefined + const category = video.category || undefined + const description = video.description || undefined const body: VideoUpdate = { name: video.name, @@ -60,10 +61,14 @@ export class VideoService { privacy: video.privacy, tags: video.tags, nsfw: video.nsfw, - commentsEnabled: video.commentsEnabled + commentsEnabled: video.commentsEnabled, + thumbnailfile: video.thumbnailfile, + previewfile: video.previewfile } - return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, body) + const data = objectToFormData(body) + + return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, data) .map(this.restExtractor.extractDataBool) .catch(this.restExtractor.handleError) } diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html index d031825bdb9ad391d0dfe601c3ec3b3447dc998b..899249778f4be37b17f8abbda397619e7f10b619 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html @@ -1,109 +1,133 @@ <div class="video-edit row" [formGroup]="form"> - - <div class="col-md-8"> - <div class="form-group"> - <label for="name">Title</label> - <input type="text" id="name" formControlName="name" /> - <div *ngIf="formErrors.name" class="form-error"> - {{ formErrors.name }} - </div> - </div> - - <div class="form-group"> - <label class="label-tags">Tags</label> <span>(press Enter to add)</span> - <tag-input - [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" - formControlName="tags" maxItems="5" modelAsStrings="true" - ></tag-input> - </div> - - <div class="form-group"> - <label for="description">Description</label> - <my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea> - - <div *ngIf="formErrors.description" class="form-error"> - {{ formErrors.description }} - </div> - </div> - </div> - - <div class="col-md-4"> - <div class="form-group"> - <label>Channel</label> - <div class="peertube-select-disabled-container"> - <select formControlName="channelId"> - <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> - </select> - </div> - </div> - - <div class="form-group"> - <label for="category">Category</label> - <div class="peertube-select-container"> - <select id="category" formControlName="category"> - <option></option> - <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> - </select> - </div> - - <div *ngIf="formErrors.category" class="form-error"> - {{ formErrors.category }} - </div> - </div> - - <div class="form-group"> - <label for="licence">Licence</label> - <div class="peertube-select-container"> - <select id="licence" formControlName="licence"> - <option></option> - <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> - </select> + <tabset class="root-tabset bootstrap"> + + <tab heading="Basic info"> + <div class="col-md-8"> + <div class="form-group"> + <label for="name">Title</label> + <input type="text" id="name" formControlName="name" /> + <div *ngIf="formErrors.name" class="form-error"> + {{ formErrors.name }} + </div> + </div> + + <div class="form-group"> + <label class="label-tags">Tags</label> <span>(press Enter to add)</span> + <tag-input + [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" + formControlName="tags" maxItems="5" modelAsStrings="true" + ></tag-input> + </div> + + <div class="form-group"> + <label for="description">Description</label> + <my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea> + + <div *ngIf="formErrors.description" class="form-error"> + {{ formErrors.description }} + </div> + </div> </div> - <div *ngIf="formErrors.licence" class="form-error"> - {{ formErrors.licence }} - </div> - </div> - - <div class="form-group"> - <label for="language">Language</label> - <div class="peertube-select-container"> - <select id="language" formControlName="language"> - <option></option> - <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> - </select> - </div> + <div class="col-md-4"> + <div class="form-group"> + <label>Channel</label> + <div class="peertube-select-disabled-container"> + <select formControlName="channelId"> + <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> + </select> + </div> + </div> + + <div class="form-group"> + <label for="category">Category</label> + <div class="peertube-select-container"> + <select id="category" formControlName="category"> + <option></option> + <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> + </select> + </div> + + <div *ngIf="formErrors.category" class="form-error"> + {{ formErrors.category }} + </div> + </div> + + <div class="form-group"> + <label for="licence">Licence</label> + <div class="peertube-select-container"> + <select id="licence" formControlName="licence"> + <option></option> + <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> + </select> + </div> + + <div *ngIf="formErrors.licence" class="form-error"> + {{ formErrors.licence }} + </div> + </div> + + <div class="form-group"> + <label for="language">Language</label> + <div class="peertube-select-container"> + <select id="language" formControlName="language"> + <option></option> + <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> + </select> + </div> + + <div *ngIf="formErrors.language" class="form-error"> + {{ formErrors.language }} + </div> + </div> + + <div class="form-group"> + <label for="privacy">Privacy</label> + <div class="peertube-select-container"> + <select id="privacy" formControlName="privacy"> + <option></option> + <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> + </select> + </div> + + <div *ngIf="formErrors.privacy" class="form-error"> + {{ formErrors.privacy }} + </div> + </div> + + <div class="form-group form-group-checkbox"> + <input type="checkbox" id="nsfw" formControlName="nsfw" /> + <label for="nsfw"></label> + <label for="nsfw">This video contains mature or explicit content</label> + </div> + + <div class="form-group form-group-checkbox"> + <input type="checkbox" id="commentsEnabled" formControlName="commentsEnabled" /> + <label for="commentsEnabled"></label> + <label for="commentsEnabled">Enable video comments</label> + </div> - <div *ngIf="formErrors.language" class="form-error"> - {{ formErrors.language }} </div> - </div> - - <div class="form-group"> - <label for="privacy">Privacy</label> - <div class="peertube-select-container"> - <select id="privacy" formControlName="privacy"> - <option></option> - <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> - </select> + </tab> + + <tab heading="Advanced settings"> + <div class="col-md-12"> + <div class="form-group"> + <my-video-image + inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile" + previewWidth="200px" previewHeight="110px" + ></my-video-image> + </div> + + <div class="form-group"> + <my-video-image + inputLabel="Upload preview" inputName="previewfile" formControlName="previewfile" + previewWidth="360px" previewHeight="200px" + ></my-video-image> + </div> </div> + </tab> - <div *ngIf="formErrors.privacy" class="form-error"> - {{ formErrors.privacy }} - </div> - </div> - - <div class="form-group form-group-checkbox"> - <input type="checkbox" id="nsfw" formControlName="nsfw" /> - <label for="nsfw"></label> - <label for="nsfw">This video contains mature or explicit content</label> - </div> - - <div class="form-group form-group-checkbox"> - <input type="checkbox" id="commentsEnabled" formControlName="commentsEnabled" /> - <label for="commentsEnabled"></label> - <label for="commentsEnabled">Enable video comments</label> - </div> + </tabset> - </div> </div> diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.scss b/client/src/app/videos/+video-edit/shared/video-edit.component.scss index 1df9d400610286ef8eac4ffb146748361272d8fd..f78336fa8f226784861968d1b7af7c2d084fd695 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.scss +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.scss @@ -47,6 +47,18 @@ .label-tags + span { font-size: 15px; } + + .root-tabset /deep/ > .nav { + margin-left: 15px; + margin-bottom: 15px; + + .nav-link { + display: flex !important; + align-items: center; + height: 30px !important; + padding: 0 15px !important; + } + } } .submit-container { diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts index 2b307d5fafd081a408468fac173ad24effd5d240..85e5cc3f596125be76242af72f6049fa197a6903 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts @@ -1,6 +1,7 @@ import { Component, Input, OnInit } from '@angular/core' import { FormBuilder, FormControl, FormGroup } from '@angular/forms' import { ActivatedRoute, Router } from '@angular/router' +import { VIDEO_IMAGE } from '@app/shared' import { NotificationsService } from 'angular2-notifications' import 'rxjs/add/observable/forkJoin' import { ServerService } from '../../../core/server' @@ -57,6 +58,8 @@ export class VideoEditComponent implements OnInit { this.formErrors['licence'] = '' this.formErrors['language'] = '' this.formErrors['description'] = '' + this.formErrors['thumbnailfile'] = '' + this.formErrors['previewfile'] = '' this.validationMessages['name'] = VIDEO_NAME.MESSAGES this.validationMessages['privacy'] = VIDEO_PRIVACY.MESSAGES @@ -65,6 +68,8 @@ export class VideoEditComponent implements OnInit { this.validationMessages['licence'] = VIDEO_LICENCE.MESSAGES this.validationMessages['language'] = VIDEO_LANGUAGE.MESSAGES this.validationMessages['description'] = VIDEO_DESCRIPTION.MESSAGES + this.validationMessages['thumbnailfile'] = VIDEO_IMAGE.MESSAGES + this.validationMessages['previewfile'] = VIDEO_IMAGE.MESSAGES this.form.addControl('name', new FormControl('', VIDEO_NAME.VALIDATORS)) this.form.addControl('privacy', new FormControl('', VIDEO_PRIVACY.VALIDATORS)) @@ -76,6 +81,8 @@ export class VideoEditComponent implements OnInit { this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS)) this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS)) this.form.addControl('tags', new FormControl('')) + this.form.addControl('thumbnailfile', new FormControl('')) + this.form.addControl('previewfile', new FormControl('')) } ngOnInit () { diff --git a/client/src/app/videos/+video-edit/shared/video-edit.module.ts b/client/src/app/videos/+video-edit/shared/video-edit.module.ts index 098a71ae6d93e7180cbb58d78023a91c8dd9ba65..1b82281bfcd06ab6546e166a724692700aba4ed9 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.module.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core' +import { VideoImageComponent } from '@app/videos/+video-edit/shared/video-image.component' import { TabsModule } from 'ngx-bootstrap/tabs' import { TagInputModule } from 'ngx-chips' import { SharedModule } from '../../../shared' @@ -12,7 +13,8 @@ import { VideoEditComponent } from './video-edit.component' ], declarations: [ - VideoEditComponent + VideoEditComponent, + VideoImageComponent ], exports: [ diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 7f41b56d8ab8771718e5b372025774bdb8825f0c..ad6452835f4d522242a05e4e86f134943c36137f 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts @@ -48,11 +48,10 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { this.buildForm() this.serverService.videoPrivaciesLoaded - .subscribe( - () => this.videoPrivacies = this.serverService.getVideoPrivacies() - ) + .subscribe(() => this.videoPrivacies = this.serverService.getVideoPrivacies()) populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) + .catch(err => console.error('Cannot populate async user video channels.', err)) const uuid: string = this.route.snapshot.params['uuid'] this.videoService.getVideo(uuid) @@ -116,5 +115,26 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { private hydrateFormFromVideo () { this.form.patchValue(this.video.toJSON()) + + const objects = [ + { + url: 'thumbnailUrl', + name: 'thumbnailfile' + }, + { + url: 'previewUrl', + name: 'previewfile' + } + ] + + for (const obj of objects) { + fetch(this.video[obj.url]) + .then(response => response.blob()) + .then(data => { + this.form.patchValue({ + [ obj.name ]: data + }) + }) + } } } diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index af90e22a19eb33f851eb4019c7f3a2d51593354f..8c173d6b35fcdd0a6608b1da3bbd2869f404472a 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -1,7 +1,7 @@ <div class="row"> <!-- We need the video container for videojs so we just hide it --> <div [hidden]="videoNotFound" id="video-container"> - <video id="video-element" class="video-js vjs-peertube-skin"></video> + <video [poster]="getVideoPoster()" id="video-element" class="video-js vjs-peertube-skin"></video> </div> <div *ngIf="videoNotFound" id="video-not-found">Video not found :'(</div> diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 7a64406e6fc424f087ed4d87187f9c7a7559ef1f..7c97f0964af48d9196c1469a1e05209583bf25c4 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -211,6 +211,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { return Account.GET_ACCOUNT_AVATAR_URL(this.video.account) } + getVideoPoster () { + if (!this.video) return '' + + return this.video.previewUrl + } + getVideoTags () { if (!this.video || Array.isArray(this.video.tags) === false) return [] diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss index 34022100200f8de3b3d3f04dc95a6bb6ee305ed7..80dd3408f223c3dc7d444d643df101099e5dd75e 100644 --- a/client/src/sass/application.scss +++ b/client/src/sass/application.scss @@ -299,34 +299,45 @@ p-datatable { } } -.nav { - font-size: 16px !important; - border: none !important; - - .nav-item .nav-link { - margin-right: 30px; - padding: 0; - border-radius: 3px; +tabset:not(.bootstrap) { + .nav { + font-size: 16px !important; border: none !important; - .tab-link { - display: flex !important; - align-items: center; - min-height: 30px !important; - padding: 0 15px; - } + .nav-item .nav-link { + margin-right: 30px; + padding: 0; + border-radius: 3px; + border: none !important; - &, & a { - color: #000 !important; - @include disable-default-a-behaviour; - } + .tab-link { + display: flex !important; + align-items: center; + min-height: 30px !important; + padding: 0 15px; + } - &.active, &:hover { - background-color: #F0F0F0; + &, & a { + color: #000 !important; + @include disable-default-a-behaviour; + } + + &.active, &:hover { + background-color: #F0F0F0; + } + + &.active { + font-weight: $font-semibold !important; + } } + } +} - &.active { - font-weight: $font-semibold !important; +tabset.bootstrap { + .nav-item .nav-link { + &, & a { + color: #000; + @include disable-default-a-behaviour; } } } diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 89163edb3f99fba5ec26148d5c4efcaaf993fa40..532afb8c0832f0119e327e65938aa5a13e64c910 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts @@ -61,6 +61,12 @@ async function getConfig (req: express.Request, res: express.Response, next: exp } }, video: { + image: { + extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, + size: { + max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max + } + }, file: { extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME } diff --git a/shared/models/config/server-config.model.ts b/shared/models/config/server-config.model.ts index fdc36bcc17f57b7c6ebdccf42bc51ff72017911f..988dd71e3635ed1056df6f7159a87aa8887adcdb 100644 --- a/shared/models/config/server-config.model.ts +++ b/shared/models/config/server-config.model.ts @@ -23,6 +23,12 @@ export interface ServerConfig { } video: { + image: { + size: { + max: number + } + extensions: string[] + }, file: { extensions: string[] } diff --git a/shared/models/videos/video-update.model.ts b/shared/models/videos/video-update.model.ts index 0b26484d7aa8da870f77a703a3d2ab8ac6923bc5..b281ace9af0c9edc23df43ae8a54cafd090178f5 100644 --- a/shared/models/videos/video-update.model.ts +++ b/shared/models/videos/video-update.model.ts @@ -11,4 +11,6 @@ export interface VideoUpdate { tags?: string[] commentsEnabled?: boolean nsfw?: boolean + thumbnailfile?: Blob + previewfile?: Blob }