diff options
author | Chocobozzz <me@florianbigard.com> | 2018-06-12 20:04:58 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-06-12 20:37:51 +0200 |
commit | 2186386cca113506791583cb07d6ccacba7af4e0 (patch) | |
tree | 3c214c0b5fbd64332624267fa6e51fd4a9cf6474 /client/src/app/videos | |
parent | 6ccdf3a23ecec5ba2eeaf487fd1fafdc7606b4bf (diff) | |
download | PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.gz PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.zst PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.zip |
Add concept of video state, and add ability to wait transcoding before
publishing a video
Diffstat (limited to 'client/src/app/videos')
6 files changed, 100 insertions, 75 deletions
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 c8cd0d679..379cf7948 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 | |||
@@ -109,6 +109,16 @@ | |||
109 | <label i18n for="commentsEnabled">Enable video comments</label> | 109 | <label i18n for="commentsEnabled">Enable video comments</label> |
110 | </div> | 110 | </div> |
111 | 111 | ||
112 | <div class="form-group form-group-checkbox"> | ||
113 | <input type="checkbox" id="waitTranscoding" formControlName="waitTranscoding" /> | ||
114 | <label for="waitTranscoding"></label> | ||
115 | <label i18n for="waitTranscoding">Wait transcoding before publishing the video</label> | ||
116 | <my-help | ||
117 | tooltipPlacement="top" helpType="custom" i18n-customHtml | ||
118 | customHtml="If you decide to not wait transcoding before publishing the video, it can be unplayable until it transcoding ends." | ||
119 | ></my-help> | ||
120 | </div> | ||
121 | |||
112 | </div> | 122 | </div> |
113 | </tab> | 123 | </tab> |
114 | 124 | ||
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 61515c0b0..ee4fd5dc1 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 | |||
@@ -47,6 +47,7 @@ export class VideoEditComponent implements OnInit { | |||
47 | const defaultValues = { | 47 | const defaultValues = { |
48 | nsfw: 'false', | 48 | nsfw: 'false', |
49 | commentsEnabled: 'true', | 49 | commentsEnabled: 'true', |
50 | waitTranscoding: 'true', | ||
50 | tags: [] | 51 | tags: [] |
51 | } | 52 | } |
52 | const obj = { | 53 | const obj = { |
@@ -55,6 +56,7 @@ export class VideoEditComponent implements OnInit { | |||
55 | channelId: this.videoValidatorsService.VIDEO_CHANNEL, | 56 | channelId: this.videoValidatorsService.VIDEO_CHANNEL, |
56 | nsfw: null, | 57 | nsfw: null, |
57 | commentsEnabled: null, | 58 | commentsEnabled: null, |
59 | waitTranscoding: null, | ||
58 | category: this.videoValidatorsService.VIDEO_CATEGORY, | 60 | category: this.videoValidatorsService.VIDEO_CATEGORY, |
59 | licence: this.videoValidatorsService.VIDEO_LICENCE, | 61 | licence: this.videoValidatorsService.VIDEO_LICENCE, |
60 | language: this.videoValidatorsService.VIDEO_LANGUAGE, | 62 | language: this.videoValidatorsService.VIDEO_LANGUAGE, |
@@ -74,13 +76,13 @@ export class VideoEditComponent implements OnInit { | |||
74 | ) | 76 | ) |
75 | 77 | ||
76 | // We will update the "support" field depending on the channel | 78 | // We will update the "support" field depending on the channel |
77 | this.form.controls['channelId'] | 79 | this.form.controls[ 'channelId' ] |
78 | .valueChanges | 80 | .valueChanges |
79 | .pipe(map(res => parseInt(res.toString(), 10))) | 81 | .pipe(map(res => parseInt(res.toString(), 10))) |
80 | .subscribe( | 82 | .subscribe( |
81 | newChannelId => { | 83 | newChannelId => { |
82 | const oldChannelId = parseInt(this.form.value['channelId'], 10) | 84 | const oldChannelId = parseInt(this.form.value[ 'channelId' ], 10) |
83 | const currentSupport = this.form.value['support'] | 85 | const currentSupport = this.form.value[ 'support' ] |
84 | 86 | ||
85 | // Not initialized yet | 87 | // Not initialized yet |
86 | if (isNaN(newChannelId)) return | 88 | if (isNaN(newChannelId)) return |
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts index 332f757d7..85afd0caa 100644 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ b/client/src/app/videos/+video-edit/video-add.component.ts | |||
@@ -164,6 +164,7 @@ export class VideoAddComponent extends FormReactive implements OnInit, OnDestroy | |||
164 | 164 | ||
165 | const privacy = this.firstStepPrivacyId.toString() | 165 | const privacy = this.firstStepPrivacyId.toString() |
166 | const nsfw = false | 166 | const nsfw = false |
167 | const waitTranscoding = true | ||
167 | const commentsEnabled = true | 168 | const commentsEnabled = true |
168 | const channelId = this.firstStepChannelId.toString() | 169 | const channelId = this.firstStepChannelId.toString() |
169 | 170 | ||
@@ -173,6 +174,7 @@ export class VideoAddComponent extends FormReactive implements OnInit, OnDestroy | |||
173 | formData.append('privacy', VideoPrivacy.PRIVATE.toString()) | 174 | formData.append('privacy', VideoPrivacy.PRIVATE.toString()) |
174 | formData.append('nsfw', '' + nsfw) | 175 | formData.append('nsfw', '' + nsfw) |
175 | formData.append('commentsEnabled', '' + commentsEnabled) | 176 | formData.append('commentsEnabled', '' + commentsEnabled) |
177 | formData.append('waitTranscoding', '' + waitTranscoding) | ||
176 | formData.append('channelId', '' + channelId) | 178 | formData.append('channelId', '' + channelId) |
177 | formData.append('videofile', videofile) | 179 | formData.append('videofile', videofile) |
178 | 180 | ||
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 4c650b121..8bd5c00ff 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -3,6 +3,10 @@ | |||
3 | <div id="video-element-wrapper"> | 3 | <div id="video-element-wrapper"> |
4 | </div> | 4 | </div> |
5 | 5 | ||
6 | <div i18n id="warning-transcoding" class="alert alert-warning" *ngIf="isVideoToTranscode()"> | ||
7 | The video is being transcoded, it may not work properly. | ||
8 | </div> | ||
9 | |||
6 | <!-- Video information --> | 10 | <!-- Video information --> |
7 | <div *ngIf="video" class="margin-content video-bottom"> | 11 | <div *ngIf="video" class="margin-content video-bottom"> |
8 | <div class="video-info"> | 12 | <div class="video-info"> |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index 00e776a69..06dd75653 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss | |||
@@ -28,6 +28,10 @@ | |||
28 | } | 28 | } |
29 | } | 29 | } |
30 | 30 | ||
31 | #warning-transcoding { | ||
32 | text-align: center; | ||
33 | } | ||
34 | |||
31 | #video-not-found { | 35 | #video-not-found { |
32 | height: 300px; | 36 | height: 300px; |
33 | line-height: 300px; | 37 | line-height: 300px; |
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 eefa43a73..498542fff 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { catchError } from 'rxjs/operators' | 1 | import { catchError } from 'rxjs/operators' |
2 | import { Component, ElementRef, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild, Inject } from '@angular/core' | 2 | import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' |
3 | import { ActivatedRoute, Router } from '@angular/router' | 3 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { RedirectService } from '@app/core/routing/redirect.service' | 4 | import { RedirectService } from '@app/core/routing/redirect.service' |
5 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | 5 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' |
@@ -10,7 +10,7 @@ import { Subscription } from 'rxjs' | |||
10 | import * as videojs from 'video.js' | 10 | import * as videojs from 'video.js' |
11 | import 'videojs-hotkeys' | 11 | import 'videojs-hotkeys' |
12 | import * as WebTorrent from 'webtorrent' | 12 | import * as WebTorrent from 'webtorrent' |
13 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | 13 | import { UserVideoRateType, VideoRateType, VideoState } from '../../../../../shared' |
14 | import '../../../assets/player/peertube-videojs-plugin' | 14 | import '../../../assets/player/peertube-videojs-plugin' |
15 | import { AuthService, ConfirmService } from '../../core' | 15 | import { AuthService, ConfirmService } from '../../core' |
16 | import { RestExtractor, VideoBlacklistService } from '../../shared' | 16 | import { RestExtractor, VideoBlacklistService } from '../../shared' |
@@ -21,7 +21,7 @@ import { MarkdownService } from '../shared' | |||
21 | import { VideoDownloadComponent } from './modal/video-download.component' | 21 | import { VideoDownloadComponent } from './modal/video-download.component' |
22 | import { VideoReportComponent } from './modal/video-report.component' | 22 | import { VideoReportComponent } from './modal/video-report.component' |
23 | import { VideoShareComponent } from './modal/video-share.component' | 23 | import { VideoShareComponent } from './modal/video-share.component' |
24 | import { getVideojsOptions, loadLocale, addContextMenu } from '../../../assets/player/peertube-player' | 24 | import { addContextMenu, getVideojsOptions, loadLocale } from '../../../assets/player/peertube-player' |
25 | import { ServerService } from '@app/core' | 25 | import { ServerService } from '@app/core' |
26 | import { I18n } from '@ngx-translate/i18n-polyfill' | 26 | import { I18n } from '@ngx-translate/i18n-polyfill' |
27 | import { environment } from '../../../environments/environment' | 27 | import { environment } from '../../../environments/environment' |
@@ -91,21 +91,21 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | this.videoService.getVideos({ currentPage: 1, itemsPerPage: 5 }, '-createdAt') | 93 | this.videoService.getVideos({ currentPage: 1, itemsPerPage: 5 }, '-createdAt') |
94 | .subscribe( | 94 | .subscribe( |
95 | data => { | 95 | data => { |
96 | this.otherVideos = data.videos | 96 | this.otherVideos = data.videos |
97 | this.updateOtherVideosDisplayed() | 97 | this.updateOtherVideosDisplayed() |
98 | }, | 98 | }, |
99 | 99 | ||
100 | err => console.error(err) | 100 | err => console.error(err) |
101 | ) | 101 | ) |
102 | 102 | ||
103 | this.paramsSub = this.route.params.subscribe(routeParams => { | 103 | this.paramsSub = this.route.params.subscribe(routeParams => { |
104 | if (this.player) { | 104 | if (this.player) { |
105 | this.player.pause() | 105 | this.player.pause() |
106 | } | 106 | } |
107 | 107 | ||
108 | const uuid = routeParams['uuid'] | 108 | const uuid = routeParams[ 'uuid' ] |
109 | 109 | ||
110 | // Video did not change | 110 | // Video did not change |
111 | if (this.video && this.video.uuid === uuid) return | 111 | if (this.video && this.video.uuid === uuid) return |
@@ -113,13 +113,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
113 | this.videoService | 113 | this.videoService |
114 | .getVideo(uuid) | 114 | .getVideo(uuid) |
115 | .pipe(catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))) | 115 | .pipe(catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))) |
116 | .subscribe( | 116 | .subscribe(video => { |
117 | video => { | 117 | const startTime = this.route.snapshot.queryParams.start |
118 | const startTime = this.route.snapshot.queryParams.start | 118 | this.onVideoFetched(video, startTime) |
119 | this.onVideoFetched(video, startTime) | 119 | .catch(err => this.handleError(err)) |
120 | .catch(err => this.handleError(err)) | 120 | }) |
121 | } | ||
122 | ) | ||
123 | }) | 121 | }) |
124 | } | 122 | } |
125 | 123 | ||
@@ -157,17 +155,17 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
157 | if (res === false) return | 155 | if (res === false) return |
158 | 156 | ||
159 | this.videoBlacklistService.blacklistVideo(this.video.id) | 157 | this.videoBlacklistService.blacklistVideo(this.video.id) |
160 | .subscribe( | 158 | .subscribe( |
161 | status => { | 159 | () => { |
162 | this.notificationsService.success( | 160 | this.notificationsService.success( |
163 | this.i18n('Success'), | 161 | this.i18n('Success'), |
164 | this.i18n('Video {{videoName}} had been blacklisted.', { videoName: this.video.name }) | 162 | this.i18n('Video {{videoName}} had been blacklisted.', { videoName: this.video.name }) |
165 | ) | 163 | ) |
166 | this.redirectService.redirectToHomepage() | 164 | this.redirectService.redirectToHomepage() |
167 | }, | 165 | }, |
168 | 166 | ||
169 | error => this.notificationsService.error(this.i18n('Error'), error.message) | 167 | error => this.notificationsService.error(this.i18n('Error'), error.message) |
170 | ) | 168 | ) |
171 | } | 169 | } |
172 | 170 | ||
173 | showMoreDescription () { | 171 | showMoreDescription () { |
@@ -188,22 +186,22 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
188 | this.descriptionLoading = true | 186 | this.descriptionLoading = true |
189 | 187 | ||
190 | this.videoService.loadCompleteDescription(this.video.descriptionPath) | 188 | this.videoService.loadCompleteDescription(this.video.descriptionPath) |
191 | .subscribe( | 189 | .subscribe( |
192 | description => { | 190 | description => { |
193 | this.completeDescriptionShown = true | 191 | this.completeDescriptionShown = true |
194 | this.descriptionLoading = false | 192 | this.descriptionLoading = false |
195 | 193 | ||
196 | this.shortVideoDescription = this.video.description | 194 | this.shortVideoDescription = this.video.description |
197 | this.completeVideoDescription = description | 195 | this.completeVideoDescription = description |
198 | 196 | ||
199 | this.updateVideoDescription(this.completeVideoDescription) | 197 | this.updateVideoDescription(this.completeVideoDescription) |
200 | }, | 198 | }, |
201 | 199 | ||
202 | error => { | 200 | error => { |
203 | this.descriptionLoading = false | 201 | this.descriptionLoading = false |
204 | this.notificationsService.error(this.i18n('Error'), error.message) | 202 | this.notificationsService.error(this.i18n('Error'), error.message) |
205 | } | 203 | } |
206 | ) | 204 | ) |
207 | } | 205 | } |
208 | 206 | ||
209 | showReportModal (event: Event) { | 207 | showReportModal (event: Event) { |
@@ -259,19 +257,19 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
259 | if (res === false) return | 257 | if (res === false) return |
260 | 258 | ||
261 | this.videoService.removeVideo(this.video.id) | 259 | this.videoService.removeVideo(this.video.id) |
262 | .subscribe( | 260 | .subscribe( |
263 | status => { | 261 | status => { |
264 | this.notificationsService.success( | 262 | this.notificationsService.success( |
265 | this.i18n('Success'), | 263 | this.i18n('Success'), |
266 | this.i18n('Video {{videoName}} deleted.', { videoName: this.video.name }) | 264 | this.i18n('Video {{videoName}} deleted.', { videoName: this.video.name }) |
267 | ) | 265 | ) |
268 | 266 | ||
269 | // Go back to the video-list. | 267 | // Go back to the video-list. |
270 | this.redirectService.redirectToHomepage() | 268 | this.redirectService.redirectToHomepage() |
271 | }, | 269 | }, |
272 | 270 | ||
273 | error => this.notificationsService.error(this.i18n('Error'), error.message) | 271 | error => this.notificationsService.error(this.i18n('Error'), error.message) |
274 | ) | 272 | ) |
275 | } | 273 | } |
276 | 274 | ||
277 | acceptedPrivacyConcern () { | 275 | acceptedPrivacyConcern () { |
@@ -279,6 +277,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
279 | this.hasAlreadyAcceptedPrivacyConcern = true | 277 | this.hasAlreadyAcceptedPrivacyConcern = true |
280 | } | 278 | } |
281 | 279 | ||
280 | isVideoToTranscode () { | ||
281 | return this.video && this.video.state.id === VideoState.TO_TRANSCODE | ||
282 | } | ||
283 | |||
282 | private updateVideoDescription (description: string) { | 284 | private updateVideoDescription (description: string) { |
283 | this.video.description = description | 285 | this.video.description = description |
284 | this.setVideoDescriptionHTML() | 286 | this.setVideoDescriptionHTML() |
@@ -294,10 +296,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
294 | } | 296 | } |
295 | 297 | ||
296 | private setVideoLikesBarTooltipText () { | 298 | private setVideoLikesBarTooltipText () { |
297 | this.likesBarTooltipText = this.i18n( | 299 | this.likesBarTooltipText = this.i18n('{{likesNumber}} likes / {{dislikesNumber}} dislikes', { |
298 | '{{likesNumber}} likes / {{dislikesNumber}} dislikes', | 300 | likesNumber: this.video.likes, |
299 | { likesNumber: this.video.likes, dislikesNumber: this.video.dislikes } | 301 | dislikesNumber: this.video.dislikes |
300 | ) | 302 | }) |
301 | } | 303 | } |
302 | 304 | ||
303 | private handleError (err: any) { | 305 | private handleError (err: any) { |
@@ -320,15 +322,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
320 | if (this.isUserLoggedIn() === false) return | 322 | if (this.isUserLoggedIn() === false) return |
321 | 323 | ||
322 | this.videoService.getUserVideoRating(this.video.id) | 324 | this.videoService.getUserVideoRating(this.video.id) |
323 | .subscribe( | 325 | .subscribe( |
324 | ratingObject => { | 326 | ratingObject => { |
325 | if (ratingObject) { | 327 | if (ratingObject) { |
326 | this.userRating = ratingObject.rating | 328 | this.userRating = ratingObject.rating |
327 | } | 329 | } |
328 | }, | 330 | }, |
329 | 331 | ||
330 | err => this.notificationsService.error(this.i18n('Error'), err.message) | 332 | err => this.notificationsService.error(this.i18n('Error'), err.message) |
331 | ) | 333 | ) |
332 | } | 334 | } |
333 | 335 | ||
334 | private async onVideoFetched (video: VideoDetails, startTime = 0) { | 336 | private async onVideoFetched (video: VideoDetails, startTime = 0) { |
@@ -409,14 +411,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
409 | } | 411 | } |
410 | 412 | ||
411 | method.call(this.videoService, this.video.id) | 413 | method.call(this.videoService, this.video.id) |
412 | .subscribe( | 414 | .subscribe( |
413 | () => { | 415 | () => { |
414 | // Update the video like attribute | 416 | // Update the video like attribute |
415 | this.updateVideoRating(this.userRating, nextRating) | 417 | this.updateVideoRating(this.userRating, nextRating) |
416 | this.userRating = nextRating | 418 | this.userRating = nextRating |
417 | }, | 419 | }, |
418 | err => this.notificationsService.error(this.i18n('Error'), err.message) | 420 | |
419 | ) | 421 | err => this.notificationsService.error(this.i18n('Error'), err.message) |
422 | ) | ||
420 | } | 423 | } |
421 | 424 | ||
422 | private updateVideoRating (oldRating: UserVideoRateType, newRating: VideoRateType) { | 425 | private updateVideoRating (oldRating: UserVideoRateType, newRating: VideoRateType) { |