]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/app/videos/+video-watch/video-watch.component.ts
Try to handle truncated markdown links
[github/Chocobozzz/PeerTube.git] / client / src / app / videos / +video-watch / video-watch.component.ts
index 498542fff211493ec5f4610869d2fb5f432424b8..995fb8e2baf229a932853ce7fbf6bee717325170 100644 (file)
@@ -1,16 +1,16 @@
 import { catchError } from 'rxjs/operators'
-import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
+import { ChangeDetectorRef, Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import { RedirectService } from '@app/core/routing/redirect.service'
 import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
 import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
 import { MetaService } from '@ngx-meta/core'
 import { NotificationsService } from 'angular2-notifications'
-import { Subscription } from 'rxjs'
+import { forkJoin, Subscription } from 'rxjs'
 import * as videojs from 'video.js'
 import 'videojs-hotkeys'
 import * as WebTorrent from 'webtorrent'
-import { UserVideoRateType, VideoRateType, VideoState } from '../../../../../shared'
+import { UserVideoRateType, VideoPrivacy, VideoRateType, VideoState } from '../../../../../shared'
 import '../../../assets/player/peertube-videojs-plugin'
 import { AuthService, ConfirmService } from '../../core'
 import { RestExtractor, VideoBlacklistService } from '../../shared'
@@ -26,6 +26,8 @@ import { ServerService } from '@app/core'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { environment } from '../../../environments/environment'
 import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
+import { VideoCaptionService } from '@app/shared/video-caption'
+import { VideoCaption } from '../../../../../shared/models/videos/video-caption.model'
 
 @Component({
   selector: 'my-video-watch',
@@ -54,6 +56,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   videoHTMLDescription = ''
   likesBarTooltipText = ''
   hasAlreadyAcceptedPrivacyConcern = false
+  remoteServerDown = false
 
   private videojsLocaleLoaded = false
   private otherVideos: Video[] = []
@@ -61,6 +64,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
   constructor (
     private elementRef: ElementRef,
+    private changeDetector: ChangeDetectorRef,
     private route: ActivatedRoute,
     private router: Router,
     private videoService: VideoService,
@@ -74,6 +78,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     private markdownService: MarkdownService,
     private zone: NgZone,
     private redirectService: RedirectService,
+    private videoCaptionService: VideoCaptionService,
     private i18n: I18n,
     @Inject(LOCALE_ID) private localeId: string
   ) {}
@@ -101,23 +106,26 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
         )
 
     this.paramsSub = this.route.params.subscribe(routeParams => {
-      if (this.player) {
-        this.player.pause()
-      }
-
       const uuid = routeParams[ 'uuid' ]
 
       // Video did not change
       if (this.video && this.video.uuid === uuid) return
+
+      if (this.player) this.player.pause()
+
       // Video did change
-      this.videoService
-          .getVideo(uuid)
-          .pipe(catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ])))
-          .subscribe(video => {
-            const startTime = this.route.snapshot.queryParams.start
-            this.onVideoFetched(video, startTime)
-                .catch(err => this.handleError(err))
-          })
+      forkJoin(
+        this.videoService.getVideo(uuid),
+        this.videoCaptionService.listCaptions(uuid)
+      )
+        .pipe(
+          catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))
+        )
+        .subscribe(([ video, captionsResult ]) => {
+          const startTime = this.route.snapshot.queryParams.start
+          this.onVideoFetched(video, captionsResult.data, startTime)
+              .catch(err => this.handleError(err))
+        })
     })
   }
 
@@ -243,7 +251,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   getVideoTags () {
     if (!this.video || Array.isArray(this.video.tags) === false) return []
 
-    return this.video.tags.join(', ')
+    return this.video.tags
   }
 
   isVideoRemovable () {
@@ -281,17 +289,16 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     return this.video && this.video.state.id === VideoState.TO_TRANSCODE
   }
 
+  hasVideoScheduledPublication () {
+    return this.video && this.video.scheduledUpdate !== undefined
+  }
+
   private updateVideoDescription (description: string) {
     this.video.description = description
     this.setVideoDescriptionHTML()
   }
 
   private setVideoDescriptionHTML () {
-    if (!this.video.description) {
-      this.videoHTMLDescription = ''
-      return
-    }
-
     this.videoHTMLDescription = this.markdownService.textMarkdownToHTML(this.video.description)
   }
 
@@ -306,15 +313,16 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     const errorMessage: string = typeof err === 'string' ? err : err.message
     if (!errorMessage) return
 
-    let message = ''
+    // Display a message in the video player instead of a notification
+    if (errorMessage.indexOf('from xs param') !== -1) {
+      this.flushPlayer()
+      this.remoteServerDown = true
+      this.changeDetector.detectChanges()
 
-    if (errorMessage.indexOf('http error') !== -1) {
-      message = this.i18n('Cannot fetch video from server, maybe down.')
-    } else {
-      message = errorMessage
+      return
     }
 
-    this.notificationsService.error(this.i18n('Error'), message)
+    this.notificationsService.error(this.i18n('Error'), errorMessage)
   }
 
   private checkUserRating () {
@@ -333,12 +341,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
         )
   }
 
-  private async onVideoFetched (video: VideoDetails, startTime = 0) {
+  private async onVideoFetched (video: VideoDetails, videoCaptions: VideoCaption[], startTime = 0) {
     this.video = video
 
     // Re init attributes
     this.descriptionLoading = false
     this.completeDescriptionShown = false
+    this.remoteServerDown = false
 
     this.updateOtherVideosDisplayed()
 
@@ -360,12 +369,19 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     this.playerElement.setAttribute('playsinline', 'true')
     playerElementWrapper.appendChild(this.playerElement)
 
+    const playerCaptions = videoCaptions.map(c => ({
+      label: c.language.label,
+      language: c.language.id,
+      src: environment.apiUrl + c.captionPath
+    }))
+
     const videojsOptions = getVideojsOptions({
       autoplay: this.isAutoplay(),
       inactivityTimeout: 2500,
       videoFiles: this.video.files,
+      videoCaptions: playerCaptions,
       playerElement: this.playerElement,
-      videoViewUrl: this.videoService.getVideoViewUrl(this.video.uuid),
+      videoViewUrl: this.video.privacy.id !== VideoPrivacy.PRIVATE ? this.videoService.getVideoViewUrl(this.video.uuid) : null,
       videoDuration: this.video.duration,
       enableHotkeys: true,
       peertubeLink: false,
@@ -469,7 +485,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   }
 
   private isAutoplay () {
-    // True by default
+    // We'll jump to the thread id, so do not play the video
+    if (this.route.snapshot.params['threadId']) return false
+
+    // Otherwise true by default
     if (!this.user) return true
 
     // Be sure the autoPlay is set to false