]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/shared/video-playlist/video-add-to-playlist.component.ts
Fix misplaced i18n tag in admin system config
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / video-playlist / video-add-to-playlist.component.ts
CommitLineData
51b34a11 1import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
f0a39880
C
2import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
3import { AuthService, Notifier } from '@app/core'
51b34a11
C
4import { Subject, Subscription } from 'rxjs'
5import { debounceTime, filter } from 'rxjs/operators'
f0a39880
C
6import { Video, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy } from '@shared/models'
7import { FormReactive, FormValidatorService, VideoPlaylistValidatorsService } from '@app/shared/forms'
8import { I18n } from '@ngx-translate/i18n-polyfill'
978c9d49 9import { secondsToTime } from '../../../assets/player/utils'
51b34a11
C
10import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
11import * as debug from 'debug'
12import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
13import { VideoExistInPlaylist } from '@shared/models/videos/playlist/video-exist-in-playlist.model'
14
15const logger = debug('peertube:playlists:VideoAddToPlaylistComponent')
f0a39880
C
16
17type PlaylistSummary = {
18 id: number
19 inPlaylist: boolean
20 displayName: string
21
a3671f07 22 playlistElementId?: number
f0a39880
C
23 startTimestamp?: number
24 stopTimestamp?: number
25}
26
27@Component({
28 selector: 'my-video-add-to-playlist',
29 styleUrls: [ './video-add-to-playlist.component.scss' ],
8dfceec4
C
30 templateUrl: './video-add-to-playlist.component.html',
31 changeDetection: ChangeDetectionStrategy.OnPush
f0a39880 32})
51b34a11 33export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, OnChanges, OnDestroy, DisableForReuseHook {
f0a39880
C
34 @Input() video: Video
35 @Input() currentVideoTimestamp: number
3a0fb65c 36 @Input() lazyLoad = false
f0a39880
C
37
38 isNewPlaylistBlockOpened = false
c06af501
RK
39 videoPlaylistSearch: string
40 videoPlaylistSearchChanged = new Subject<string>()
f0a39880
C
41 videoPlaylists: PlaylistSummary[] = []
42 timestampOptions: {
43 startTimestampEnabled: boolean
44 startTimestamp: number
45 stopTimestampEnabled: boolean
46 stopTimestamp: number
47 }
48 displayOptions = false
49
51b34a11
C
50 private disabled = false
51
52 private listenToPlaylistChangeSub: Subscription
53 private playlistsData: VideoPlaylist[] = []
54
f0a39880
C
55 constructor (
56 protected formValidatorService: FormValidatorService,
57 private authService: AuthService,
58 private notifier: Notifier,
59 private i18n: I18n,
60 private videoPlaylistService: VideoPlaylistService,
8dfceec4
C
61 private videoPlaylistValidatorsService: VideoPlaylistValidatorsService,
62 private cd: ChangeDetectorRef
f0a39880
C
63 ) {
64 super()
65 }
66
67 get user () {
68 return this.authService.getUser()
69 }
70
71 ngOnInit () {
f0a39880 72 this.buildForm({
978c9d49 73 displayName: this.videoPlaylistValidatorsService.VIDEO_PLAYLIST_DISPLAY_NAME
f0a39880 74 })
c06af501 75
51b34a11
C
76 this.videoPlaylistService.listenToMyAccountPlaylistsChange()
77 .subscribe(result => {
78 this.playlistsData = result.data
79
80 this.videoPlaylistService.runPlaylistCheck(this.video.id)
81 })
82
c06af501 83 this.videoPlaylistSearchChanged
51b34a11
C
84 .pipe(debounceTime(500))
85 .subscribe(() => this.load())
86
87 if (this.lazyLoad === false) this.load()
1c8ddbfa
C
88 }
89
90 ngOnChanges (simpleChanges: SimpleChanges) {
91 if (simpleChanges['video']) {
8d51015b 92 this.reload()
1c8ddbfa
C
93 }
94 }
95
51b34a11
C
96 ngOnDestroy () {
97 this.unsubscribePlaylistChanges()
98 }
1c8ddbfa 99
51b34a11
C
100 disableForReuse () {
101 this.disabled = true
102 }
103
104 enabledForReuse () {
105 this.disabled = false
3a0fb65c
C
106 }
107
8d51015b 108 reload () {
51b34a11
C
109 logger('Reloading component')
110
1c8ddbfa 111 this.videoPlaylists = []
c06af501 112 this.videoPlaylistSearch = undefined
1c8ddbfa 113
51b34a11
C
114 this.resetOptions(true)
115 this.load()
1c8ddbfa
C
116
117 this.cd.markForCheck()
118 }
119
3a0fb65c 120 load () {
51b34a11
C
121 logger('Loading component')
122
123 this.listenToPlaylistChanges()
124
125 this.videoPlaylistService.listMyPlaylistWithCache(this.user, this.videoPlaylistSearch)
126 .subscribe(playlistsResult => {
127 this.playlistsData = playlistsResult.data
128
129 this.videoPlaylistService.runPlaylistCheck(this.video.id)
130 })
f0a39880
C
131 }
132
133 openChange (opened: boolean) {
134 if (opened === false) {
135 this.isNewPlaylistBlockOpened = false
136 this.displayOptions = false
137 }
138 }
139
140 openCreateBlock (event: Event) {
141 event.preventDefault()
142
143 this.isNewPlaylistBlockOpened = true
144 }
145
146 togglePlaylist (event: Event, playlist: PlaylistSummary) {
147 event.preventDefault()
148
149 if (playlist.inPlaylist === true) {
150 this.removeVideoFromPlaylist(playlist)
151 } else {
152 this.addVideoInPlaylist(playlist)
153 }
154
155 playlist.inPlaylist = !playlist.inPlaylist
156 this.resetOptions()
8dfceec4
C
157
158 this.cd.markForCheck()
f0a39880
C
159 }
160
161 createPlaylist () {
978c9d49 162 const displayName = this.form.value[ 'displayName' ]
f0a39880
C
163
164 const videoPlaylistCreate: VideoPlaylistCreate = {
165 displayName,
166 privacy: VideoPlaylistPrivacy.PRIVATE
167 }
168
169 this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate).subscribe(
51b34a11 170 () => {
f0a39880 171 this.isNewPlaylistBlockOpened = false
8dfceec4
C
172
173 this.cd.markForCheck()
f0a39880
C
174 },
175
176 err => this.notifier.error(err.message)
177 )
178 }
179
180 resetOptions (resetTimestamp = false) {
181 this.displayOptions = false
182
183 this.timestampOptions = {} as any
184 this.timestampOptions.startTimestampEnabled = false
185 this.timestampOptions.stopTimestampEnabled = false
186
187 if (resetTimestamp) {
188 this.timestampOptions.startTimestamp = 0
189 this.timestampOptions.stopTimestamp = this.video.duration
190 }
191 }
192
193 formatTimestamp (playlist: PlaylistSummary) {
194 const start = playlist.startTimestamp ? secondsToTime(playlist.startTimestamp) : ''
195 const stop = playlist.stopTimestamp ? secondsToTime(playlist.stopTimestamp) : ''
196
197 return `(${start}-${stop})`
198 }
199
c06af501
RK
200 onVideoPlaylistSearchChanged () {
201 this.videoPlaylistSearchChanged.next()
202 }
203
f0a39880 204 private removeVideoFromPlaylist (playlist: PlaylistSummary) {
a3671f07 205 if (!playlist.playlistElementId) return
bfbd9128 206
51b34a11 207 this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, playlist.playlistElementId, this.video.id)
f0a39880
C
208 .subscribe(
209 () => {
210 this.notifier.success(this.i18n('Video removed from {{name}}', { name: playlist.displayName }))
f0a39880
C
211 },
212
213 err => {
214 this.notifier.error(err.message)
8dfceec4
C
215 },
216
217 () => this.cd.markForCheck()
f0a39880
C
218 )
219 }
220
51b34a11
C
221 private listenToPlaylistChanges () {
222 this.unsubscribePlaylistChanges()
223
224 this.listenToPlaylistChangeSub = this.videoPlaylistService.listenToVideoPlaylistChange(this.video.id)
225 .pipe(filter(() => this.disabled === false))
226 .subscribe(existResult => this.rebuildPlaylists(existResult))
227 }
228
229 private unsubscribePlaylistChanges () {
230 if (this.listenToPlaylistChangeSub) {
231 this.listenToPlaylistChangeSub.unsubscribe()
232 this.listenToPlaylistChangeSub = undefined
233 }
234 }
235
236 private rebuildPlaylists (existResult: VideoExistInPlaylist[]) {
237 logger('Got existing results for %d.', this.video.id, existResult)
238
239 this.videoPlaylists = []
240 for (const playlist of this.playlistsData) {
241 const existingPlaylist = existResult.find(p => p.playlistId === playlist.id)
242
243 this.videoPlaylists.push({
244 id: playlist.id,
245 displayName: playlist.displayName,
246 inPlaylist: !!existingPlaylist,
247 playlistElementId: existingPlaylist ? existingPlaylist.playlistElementId : undefined,
248 startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
249 stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
250 })
251 }
252
253 logger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists)
254
255 this.cd.markForCheck()
256 }
257
f0a39880
C
258 private addVideoInPlaylist (playlist: PlaylistSummary) {
259 const body: VideoPlaylistElementCreate = { videoId: this.video.id }
260
261 if (this.timestampOptions.startTimestampEnabled) body.startTimestamp = this.timestampOptions.startTimestamp
262 if (this.timestampOptions.stopTimestampEnabled) body.stopTimestamp = this.timestampOptions.stopTimestamp
263
264 this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
265 .subscribe(
51b34a11 266 () => {
f0a39880
C
267 const message = body.startTimestamp || body.stopTimestamp
268 ? this.i18n('Video added in {{n}} at timestamps {{t}}', { n: playlist.displayName, t: this.formatTimestamp(playlist) })
269 : this.i18n('Video added in {{n}}', { n: playlist.displayName })
270
271 this.notifier.success(message)
272 },
273
274 err => {
275 this.notifier.error(err.message)
8dfceec4
C
276 },
277
278 () => this.cd.markForCheck()
f0a39880
C
279 )
280 }
281}