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