Add video miniature dropdown
[oweals/peertube.git] / client / src / app / shared / video-playlist / video-add-to-playlist.component.ts
1 import { Component, Input, OnInit } from '@angular/core'
2 import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
3 import { AuthService, Notifier } from '@app/core'
4 import { forkJoin } from 'rxjs'
5 import { Video, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy } from '@shared/models'
6 import { FormReactive, FormValidatorService, VideoPlaylistValidatorsService } from '@app/shared/forms'
7 import { I18n } from '@ngx-translate/i18n-polyfill'
8 import { secondsToTime } from '../../../assets/player/utils'
9
10 type PlaylistSummary = {
11   id: number
12   inPlaylist: boolean
13   displayName: string
14
15   startTimestamp?: number
16   stopTimestamp?: number
17 }
18
19 @Component({
20   selector: 'my-video-add-to-playlist',
21   styleUrls: [ './video-add-to-playlist.component.scss' ],
22   templateUrl: './video-add-to-playlist.component.html'
23 })
24 export class VideoAddToPlaylistComponent extends FormReactive implements OnInit {
25   @Input() video: Video
26   @Input() currentVideoTimestamp: number
27   @Input() lazyLoad = false
28
29   isNewPlaylistBlockOpened = false
30   videoPlaylists: PlaylistSummary[] = []
31   timestampOptions: {
32     startTimestampEnabled: boolean
33     startTimestamp: number
34     stopTimestampEnabled: boolean
35     stopTimestamp: number
36   }
37   displayOptions = false
38
39   constructor (
40     protected formValidatorService: FormValidatorService,
41     private authService: AuthService,
42     private notifier: Notifier,
43     private i18n: I18n,
44     private videoPlaylistService: VideoPlaylistService,
45     private videoPlaylistValidatorsService: VideoPlaylistValidatorsService
46   ) {
47     super()
48   }
49
50   get user () {
51     return this.authService.getUser()
52   }
53
54   ngOnInit () {
55     this.resetOptions(true)
56
57     this.buildForm({
58       displayName: this.videoPlaylistValidatorsService.VIDEO_PLAYLIST_DISPLAY_NAME
59     })
60
61     if (this.lazyLoad !== true) this.load()
62   }
63
64   load () {
65     forkJoin([
66       this.videoPlaylistService.listAccountPlaylists(this.user.account, '-updatedAt'),
67       this.videoPlaylistService.doesVideoExistInPlaylist(this.video.id)
68     ])
69       .subscribe(
70         ([ playlistsResult, existResult ]) => {
71           for (const playlist of playlistsResult.data) {
72             const existingPlaylist = existResult[ this.video.id ].find(p => p.playlistId === playlist.id)
73
74             this.videoPlaylists.push({
75               id: playlist.id,
76               displayName: playlist.displayName,
77               inPlaylist: !!existingPlaylist,
78               startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
79               stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
80             })
81           }
82         }
83       )
84   }
85
86   openChange (opened: boolean) {
87     if (opened === false) {
88       this.isNewPlaylistBlockOpened = false
89       this.displayOptions = false
90     }
91   }
92
93   openCreateBlock (event: Event) {
94     event.preventDefault()
95
96     this.isNewPlaylistBlockOpened = true
97   }
98
99   togglePlaylist (event: Event, playlist: PlaylistSummary) {
100     event.preventDefault()
101
102     if (playlist.inPlaylist === true) {
103       this.removeVideoFromPlaylist(playlist)
104     } else {
105       this.addVideoInPlaylist(playlist)
106     }
107
108     playlist.inPlaylist = !playlist.inPlaylist
109     this.resetOptions()
110   }
111
112   createPlaylist () {
113     const displayName = this.form.value[ 'displayName' ]
114
115     const videoPlaylistCreate: VideoPlaylistCreate = {
116       displayName,
117       privacy: VideoPlaylistPrivacy.PRIVATE
118     }
119
120     this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate).subscribe(
121       res => {
122         this.videoPlaylists.push({
123           id: res.videoPlaylist.id,
124           displayName,
125           inPlaylist: false
126         })
127
128         this.isNewPlaylistBlockOpened = false
129       },
130
131       err => this.notifier.error(err.message)
132     )
133   }
134
135   resetOptions (resetTimestamp = false) {
136     this.displayOptions = false
137
138     this.timestampOptions = {} as any
139     this.timestampOptions.startTimestampEnabled = false
140     this.timestampOptions.stopTimestampEnabled = false
141
142     if (resetTimestamp) {
143       this.timestampOptions.startTimestamp = 0
144       this.timestampOptions.stopTimestamp = this.video.duration
145     }
146   }
147
148   formatTimestamp (playlist: PlaylistSummary) {
149     const start = playlist.startTimestamp ? secondsToTime(playlist.startTimestamp) : ''
150     const stop = playlist.stopTimestamp ? secondsToTime(playlist.stopTimestamp) : ''
151
152     return `(${start}-${stop})`
153   }
154
155   private removeVideoFromPlaylist (playlist: PlaylistSummary) {
156     this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, this.video.id)
157         .subscribe(
158           () => {
159             this.notifier.success(this.i18n('Video removed from {{name}}', { name: playlist.displayName }))
160
161             playlist.inPlaylist = false
162           },
163
164           err => {
165             this.notifier.error(err.message)
166
167             playlist.inPlaylist = true
168           }
169         )
170   }
171
172   private addVideoInPlaylist (playlist: PlaylistSummary) {
173     const body: VideoPlaylistElementCreate = { videoId: this.video.id }
174
175     if (this.timestampOptions.startTimestampEnabled) body.startTimestamp = this.timestampOptions.startTimestamp
176     if (this.timestampOptions.stopTimestampEnabled) body.stopTimestamp = this.timestampOptions.stopTimestamp
177
178     this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
179       .subscribe(
180         () => {
181           playlist.inPlaylist = true
182
183           playlist.startTimestamp = body.startTimestamp
184           playlist.stopTimestamp = body.stopTimestamp
185
186           const message = body.startTimestamp || body.stopTimestamp
187             ? this.i18n('Video added in {{n}} at timestamps {{t}}', { n: playlist.displayName, t: this.formatTimestamp(playlist) })
188             : this.i18n('Video added in {{n}}', { n: playlist.displayName })
189
190           this.notifier.success(message)
191         },
192
193         err => {
194           this.notifier.error(err.message)
195
196           playlist.inPlaylist = false
197         }
198       )
199   }
200 }