]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
only count comments from people other than the video author
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-playlist / video-add-to-playlist.component.ts
index 757ffa099791eafe62ac735cb0c49ee16cfb31e5..681e5becd0e40e84704375cce29fbbbb3d7e83d9 100644 (file)
@@ -3,21 +3,34 @@ import { Subject, Subscription } from 'rxjs'
 import { debounceTime, filter } from 'rxjs/operators'
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
 import { AuthService, DisableForReuseHook, Notifier } from '@app/core'
-import { FormReactive, FormValidatorService, VideoPlaylistValidatorsService } from '@app/shared/shared-forms'
-import { Video, VideoExistInPlaylist, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy } from '@shared/models'
+import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
+import {
+  Video,
+  VideoExistInPlaylist,
+  VideoPlaylistCreate,
+  VideoPlaylistElementCreate,
+  VideoPlaylistElementUpdate,
+  VideoPlaylistPrivacy
+} from '@shared/models'
 import { secondsToTime } from '../../../assets/player/utils'
+import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators'
 import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service'
 
 const logger = debug('peertube:playlists:VideoAddToPlaylistComponent')
 
+type PlaylistElement = {
+  enabled: boolean
+  playlistElementId?: number
+  startTimestamp?: number
+  stopTimestamp?: number
+}
+
 type PlaylistSummary = {
   id: number
-  inPlaylist: boolean
   displayName: string
+  optionalRowDisplayed: boolean
 
-  playlistElementId?: number
-  startTimestamp?: number
-  stopTimestamp?: number
+  elements: PlaylistElement[]
 }
 
 @Component({
@@ -32,16 +45,11 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
   @Input() lazyLoad = false
 
   isNewPlaylistBlockOpened = false
+
   videoPlaylistSearch: string
   videoPlaylistSearchChanged = new Subject<string>()
+
   videoPlaylists: PlaylistSummary[] = []
-  timestampOptions: {
-    startTimestampEnabled: boolean
-    startTimestamp: number
-    stopTimestampEnabled: boolean
-    stopTimestamp: number
-  }
-  displayOptions = false
 
   private disabled = false
 
@@ -53,7 +61,6 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
     private authService: AuthService,
     private notifier: Notifier,
     private videoPlaylistService: VideoPlaylistService,
-    private videoPlaylistValidatorsService: VideoPlaylistValidatorsService,
     private cd: ChangeDetectorRef
   ) {
     super()
@@ -65,7 +72,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
 
   ngOnInit () {
     this.buildForm({
-      displayName: this.videoPlaylistValidatorsService.VIDEO_PLAYLIST_DISPLAY_NAME
+      displayName: VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR
     })
 
     this.videoPlaylistService.listenToMyAccountPlaylistsChange()
@@ -106,7 +113,6 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
     this.videoPlaylists = []
     this.videoPlaylistSearch = undefined
 
-    this.resetOptions(true)
     this.load()
 
     this.cd.markForCheck()
@@ -115,7 +121,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
   load () {
     logger('Loading component')
 
-    this.listenToPlaylistChanges()
+    this.listenToVideoPlaylistChange()
 
     this.videoPlaylistService.listMyPlaylistWithCache(this.user, this.videoPlaylistSearch)
         .subscribe(playlistsResult => {
@@ -128,7 +134,6 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
   openChange (opened: boolean) {
     if (opened === false) {
       this.isNewPlaylistBlockOpened = false
-      this.displayOptions = false
     }
   }
 
@@ -138,17 +143,49 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
     this.isNewPlaylistBlockOpened = true
   }
 
-  togglePlaylist (event: Event, playlist: PlaylistSummary) {
-    event.preventDefault()
+  toggleMainPlaylist (e: Event, playlist: PlaylistSummary) {
+    e.preventDefault()
+
+    if (this.isPresentMultipleTimes(playlist) || playlist.optionalRowDisplayed) return
 
-    if (playlist.inPlaylist === true) {
-      this.removeVideoFromPlaylist(playlist)
+    if (playlist.elements.length === 0) {
+      const element: PlaylistElement = {
+        enabled: true,
+        playlistElementId: undefined,
+        startTimestamp: 0,
+        stopTimestamp: this.video.duration
+      }
+
+      this.addVideoInPlaylist(playlist, element)
     } else {
-      this.addVideoInPlaylist(playlist)
+      this.removeVideoFromPlaylist(playlist, playlist.elements[0].playlistElementId)
+      playlist.elements = []
     }
 
-    playlist.inPlaylist = !playlist.inPlaylist
-    this.resetOptions()
+    this.cd.markForCheck()
+  }
+
+  toggleOptionalPlaylist (e: Event, playlist: PlaylistSummary, element: PlaylistElement, startTimestamp: number, stopTimestamp: number) {
+    e.preventDefault()
+
+    if (element.enabled) {
+      this.removeVideoFromPlaylist(playlist, element.playlistElementId)
+      element.enabled = false
+
+      // Hide optional rows pane when the user unchecked all the playlists
+      if (this.isPrimaryCheckboxChecked(playlist) === false) {
+        playlist.optionalRowDisplayed = false
+      }
+    } else {
+      const element: PlaylistElement = {
+        enabled: true,
+        playlistElementId: undefined,
+        startTimestamp,
+        stopTimestamp
+      }
+
+      this.addVideoInPlaylist(playlist, element)
+    }
 
     this.cd.markForCheck()
   }
@@ -172,34 +209,99 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
     )
   }
 
-  resetOptions (resetTimestamp = false) {
-    this.displayOptions = false
+  onVideoPlaylistSearchChanged () {
+    this.videoPlaylistSearchChanged.next()
+  }
 
-    this.timestampOptions = {} as any
-    this.timestampOptions.startTimestampEnabled = false
-    this.timestampOptions.stopTimestampEnabled = false
+  isPrimaryCheckboxChecked (playlist: PlaylistSummary) {
+    return playlist.elements.filter(e => e.enabled)
+                            .length !== 0
+  }
 
-    if (resetTimestamp) {
-      this.timestampOptions.startTimestamp = 0
-      this.timestampOptions.stopTimestamp = this.video.duration
-    }
+  toggleOptionalRow (playlist: PlaylistSummary) {
+    playlist.optionalRowDisplayed = !playlist.optionalRowDisplayed
+
+    this.cd.markForCheck()
   }
 
-  formatTimestamp (playlist: PlaylistSummary) {
-    const start = playlist.startTimestamp ? secondsToTime(playlist.startTimestamp) : ''
-    const stop = playlist.stopTimestamp ? secondsToTime(playlist.stopTimestamp) : ''
+  getPrimaryInputName (playlist: PlaylistSummary) {
+    return 'in-playlist-primary-' + playlist.id
+  }
 
-    return `(${start}-${stop})`
+  getOptionalInputName (playlist: PlaylistSummary, element?: PlaylistElement) {
+    const suffix = element
+      ? '-' + element.playlistElementId
+      : ''
+
+    return 'in-playlist-optional-' + playlist.id + suffix
   }
 
-  onVideoPlaylistSearchChanged () {
-    this.videoPlaylistSearchChanged.next()
+  buildOptionalRowElements (playlist: PlaylistSummary) {
+    const elements = playlist.elements
+
+    const lastElement = elements.length === 0
+      ? undefined
+      : elements[elements.length - 1]
+
+    // Build an empty last element
+    if (!lastElement || lastElement.enabled === true) {
+      elements.push({
+        enabled: false,
+        startTimestamp: 0,
+        stopTimestamp: this.video.duration
+      })
+    }
+
+    return elements
+  }
+
+  isPresentMultipleTimes (playlist: PlaylistSummary) {
+    return playlist.elements.filter(e => e.enabled === true).length > 1
+  }
+
+  onElementTimestampUpdate (playlist: PlaylistSummary, element: PlaylistElement) {
+    if (!element.playlistElementId || element.enabled === false) return
+
+    const body: VideoPlaylistElementUpdate = {
+      startTimestamp: element.startTimestamp,
+      stopTimestamp: element.stopTimestamp
+    }
+
+    this.videoPlaylistService.updateVideoOfPlaylist(playlist.id, element.playlistElementId, body, this.video.id)
+        .subscribe(
+          () => {
+            this.notifier.success($localize`Timestamps updated`)
+          },
+
+          err => {
+            this.notifier.error(err.message)
+          },
+
+          () => this.cd.markForCheck()
+        )
   }
 
-  private removeVideoFromPlaylist (playlist: PlaylistSummary) {
-    if (!playlist.playlistElementId) return
+  private isOptionalRowDisplayed (playlist: PlaylistSummary) {
+    const elements = playlist.elements.filter(e => e.enabled)
+
+    if (elements.length > 1) return true
 
-    this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, playlist.playlistElementId, this.video.id)
+    if (elements.length === 1) {
+      const element = elements[0]
+
+      if (
+        (element.startTimestamp && element.startTimestamp !== 0) ||
+        (element.stopTimestamp && element.stopTimestamp !== this.video.duration)
+      ) {
+        return true
+      }
+    }
+
+    return false
+  }
+
+  private removeVideoFromPlaylist (playlist: PlaylistSummary, elementId: number) {
+    this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, elementId, this.video.id)
         .subscribe(
           () => {
             this.notifier.success($localize`Video removed from ${playlist.displayName}`)
@@ -213,7 +315,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
         )
   }
 
-  private listenToPlaylistChanges () {
+  private listenToVideoPlaylistChange () {
     this.unsubscribePlaylistChanges()
 
     this.listenToPlaylistChangeSub = this.videoPlaylistService.listenToVideoPlaylistChange(this.video.id)
@@ -231,18 +333,30 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
   private rebuildPlaylists (existResult: VideoExistInPlaylist[]) {
     logger('Got existing results for %d.', this.video.id, existResult)
 
+    const oldPlaylists = this.videoPlaylists
+
     this.videoPlaylists = []
     for (const playlist of this.playlistsData) {
-      const existingPlaylist = existResult.find(p => p.playlistId === playlist.id)
+      const existingPlaylists = existResult.filter(p => p.playlistId === playlist.id)
 
-      this.videoPlaylists.push({
+      const playlistSummary = {
         id: playlist.id,
+        optionalRowDisplayed: false,
         displayName: playlist.displayName,
-        inPlaylist: !!existingPlaylist,
-        playlistElementId: existingPlaylist ? existingPlaylist.playlistElementId : undefined,
-        startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
-        stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
-      })
+        elements: existingPlaylists.map(e => ({
+          enabled: true,
+          playlistElementId: e.playlistElementId,
+          startTimestamp: e.startTimestamp || 0,
+          stopTimestamp: e.stopTimestamp || this.video.duration
+        }))
+      }
+
+      const oldPlaylist = oldPlaylists.find(p => p.id === playlist.id)
+      playlistSummary.optionalRowDisplayed = oldPlaylist
+        ? oldPlaylist.optionalRowDisplayed
+        : this.isOptionalRowDisplayed(playlistSummary)
+
+      this.videoPlaylists.push(playlistSummary)
     }
 
     logger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists)
@@ -250,20 +364,22 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
     this.cd.markForCheck()
   }
 
-  private addVideoInPlaylist (playlist: PlaylistSummary) {
+  private addVideoInPlaylist (playlist: PlaylistSummary, element: PlaylistElement) {
     const body: VideoPlaylistElementCreate = { videoId: this.video.id }
 
-    if (this.timestampOptions.startTimestampEnabled) body.startTimestamp = this.timestampOptions.startTimestamp
-    if (this.timestampOptions.stopTimestampEnabled) body.stopTimestamp = this.timestampOptions.stopTimestamp
+    if (element.startTimestamp) body.startTimestamp = element.startTimestamp
+    if (element.stopTimestamp && element.stopTimestamp !== this.video.duration) body.stopTimestamp = element.stopTimestamp
 
     this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
       .subscribe(
-        () => {
+        res => {
           const message = body.startTimestamp || body.stopTimestamp
-            ? $localize`Video added in ${playlist.displayName} at timestamps ${this.formatTimestamp(playlist)}`
+            ? $localize`Video added in ${playlist.displayName} at timestamps ${this.formatTimestamp(element)}`
             : $localize`Video added in ${playlist.displayName}`
 
           this.notifier.success(message)
+
+          if (element) element.playlistElementId = res.videoPlaylistElement.id
         },
 
         err => {
@@ -273,4 +389,11 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
         () => this.cd.markForCheck()
       )
   }
+
+  private formatTimestamp (element: PlaylistElement) {
+    const start = element.startTimestamp ? secondsToTime(element.startTimestamp) : ''
+    const stop = element.stopTimestamp ? secondsToTime(element.stopTimestamp) : ''
+
+    return `(${start}-${stop})`
+  }
 }