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