]>
Commit | Line | Data |
---|---|---|
c5a1ae50 C |
1 | import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' |
2 | import { Notifier, ServerService } from '@app/core' | |
f0a39880 C |
3 | import { AuthService } from '../../core/auth' |
4 | import { ConfirmService } from '../../core/confirm' | |
5 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | |
6 | import { Video } from '@app/shared/video/video.model' | |
15e9d5ca | 7 | import { Subject, Subscription } from 'rxjs' |
f0a39880 C |
8 | import { ActivatedRoute } from '@angular/router' |
9 | import { VideoService } from '@app/shared/video/video.service' | |
c5a1ae50 C |
10 | import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' |
11 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | |
12 | import { I18n } from '@ngx-translate/i18n-polyfill' | |
13 | import { secondsToTime } from '../../../assets/player/utils' | |
14 | import { VideoPlaylistElementUpdate } from '@shared/models' | |
15 | import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' | |
15e9d5ca C |
16 | import { CdkDragDrop, CdkDragMove } from '@angular/cdk/drag-drop' |
17 | import { throttleTime } from 'rxjs/operators' | |
f0a39880 C |
18 | |
19 | @Component({ | |
20 | selector: 'my-account-video-playlist-elements', | |
21 | templateUrl: './my-account-video-playlist-elements.component.html', | |
22 | styleUrls: [ './my-account-video-playlist-elements.component.scss' ] | |
23 | }) | |
24 | export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy { | |
c5a1ae50 C |
25 | @ViewChild('moreDropdown') moreDropdown: NgbDropdown |
26 | ||
f0a39880 | 27 | videos: Video[] = [] |
c5a1ae50 | 28 | playlist: VideoPlaylist |
f0a39880 C |
29 | |
30 | pagination: ComponentPagination = { | |
31 | currentPage: 1, | |
32 | itemsPerPage: 10, | |
33 | totalItems: null | |
34 | } | |
35 | ||
c5a1ae50 C |
36 | displayTimestampOptions = false |
37 | ||
38 | timestampOptions: { | |
39 | startTimestampEnabled: boolean | |
40 | startTimestamp: number | |
41 | stopTimestampEnabled: boolean | |
42 | stopTimestamp: number | |
43 | } = {} as any | |
44 | ||
f0a39880 C |
45 | private videoPlaylistId: string | number |
46 | private paramsSub: Subscription | |
15e9d5ca | 47 | private dragMoveSubject = new Subject<number>() |
f0a39880 C |
48 | |
49 | constructor ( | |
50 | private authService: AuthService, | |
c5a1ae50 | 51 | private serverService: ServerService, |
f0a39880 C |
52 | private notifier: Notifier, |
53 | private confirmService: ConfirmService, | |
54 | private route: ActivatedRoute, | |
c5a1ae50 C |
55 | private i18n: I18n, |
56 | private videoService: VideoService, | |
57 | private videoPlaylistService: VideoPlaylistService | |
f0a39880 C |
58 | ) {} |
59 | ||
60 | ngOnInit () { | |
61 | this.paramsSub = this.route.params.subscribe(routeParams => { | |
62 | this.videoPlaylistId = routeParams[ 'videoPlaylistId' ] | |
63 | this.loadElements() | |
c5a1ae50 C |
64 | |
65 | this.loadPlaylistInfo() | |
f0a39880 | 66 | }) |
15e9d5ca C |
67 | |
68 | this.dragMoveSubject.asObservable() | |
69 | .pipe(throttleTime(200)) | |
70 | .subscribe(y => this.checkScroll(y)) | |
f0a39880 C |
71 | } |
72 | ||
73 | ngOnDestroy () { | |
74 | if (this.paramsSub) this.paramsSub.unsubscribe() | |
75 | } | |
76 | ||
15e9d5ca C |
77 | drop (event: CdkDragDrop<any>) { |
78 | const previousIndex = event.previousIndex | |
79 | const newIndex = event.currentIndex | |
80 | ||
81 | if (previousIndex === newIndex) return | |
82 | ||
83 | const oldPosition = this.videos[previousIndex].playlistElement.position | |
84 | const insertAfter = newIndex === 0 ? 0 : this.videos[newIndex].playlistElement.position | |
85 | ||
86 | this.videoPlaylistService.reorderPlaylist(this.playlist.id, oldPosition, insertAfter) | |
87 | .subscribe( | |
88 | () => { /* nothing to do */ }, | |
89 | ||
90 | err => this.notifier.error(err.message) | |
91 | ) | |
92 | ||
93 | const video = this.videos[previousIndex] | |
94 | ||
95 | this.videos.splice(previousIndex, 1) | |
96 | this.videos.splice(newIndex, 0, video) | |
97 | ||
98 | this.reorderClientPositions() | |
99 | } | |
100 | ||
101 | onDragMove (event: CdkDragMove<any>) { | |
102 | this.dragMoveSubject.next(event.pointerPosition.y) | |
103 | } | |
104 | ||
105 | checkScroll (pointerY: number) { | |
106 | // FIXME: Uncomment when https://github.com/angular/material2/issues/14098 is fixed | |
107 | // FIXME: Remove when https://github.com/angular/material2/issues/13588 is implemented | |
108 | // if (pointerY < 150) { | |
109 | // window.scrollBy({ | |
110 | // left: 0, | |
111 | // top: -20, | |
112 | // behavior: 'smooth' | |
113 | // }) | |
114 | // | |
115 | // return | |
116 | // } | |
117 | // | |
118 | // if (window.innerHeight - pointerY <= 50) { | |
119 | // window.scrollBy({ | |
120 | // left: 0, | |
121 | // top: 20, | |
122 | // behavior: 'smooth' | |
123 | // }) | |
124 | // } | |
125 | } | |
126 | ||
c5a1ae50 C |
127 | isVideoBlur (video: Video) { |
128 | return video.isVideoNSFWForUser(this.authService.getUser(), this.serverService.getConfig()) | |
129 | } | |
130 | ||
131 | removeFromPlaylist (video: Video) { | |
132 | this.videoPlaylistService.removeVideoFromPlaylist(this.playlist.id, video.id) | |
133 | .subscribe( | |
134 | () => { | |
135 | this.notifier.success(this.i18n('Video removed from {{name}}', { name: this.playlist.displayName })) | |
136 | ||
137 | this.videos = this.videos.filter(v => v.id !== video.id) | |
15e9d5ca | 138 | this.reorderClientPositions() |
c5a1ae50 C |
139 | }, |
140 | ||
141 | err => this.notifier.error(err.message) | |
142 | ) | |
143 | ||
144 | this.moreDropdown.close() | |
145 | } | |
146 | ||
147 | updateTimestamps (video: Video) { | |
148 | const body: VideoPlaylistElementUpdate = {} | |
149 | ||
150 | body.startTimestamp = this.timestampOptions.startTimestampEnabled ? this.timestampOptions.startTimestamp : null | |
151 | body.stopTimestamp = this.timestampOptions.stopTimestampEnabled ? this.timestampOptions.stopTimestamp : null | |
152 | ||
153 | this.videoPlaylistService.updateVideoOfPlaylist(this.playlist.id, video.id, body) | |
154 | .subscribe( | |
155 | () => { | |
156 | this.notifier.success(this.i18n('Timestamps updated')) | |
157 | ||
158 | video.playlistElement.startTimestamp = body.startTimestamp | |
159 | video.playlistElement.stopTimestamp = body.stopTimestamp | |
160 | }, | |
161 | ||
162 | err => this.notifier.error(err.message) | |
163 | ) | |
164 | ||
165 | this.moreDropdown.close() | |
166 | } | |
167 | ||
f0a39880 C |
168 | onNearOfBottom () { |
169 | // Last page | |
170 | if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return | |
171 | ||
172 | this.pagination.currentPage += 1 | |
173 | this.loadElements() | |
174 | } | |
175 | ||
c5a1ae50 C |
176 | formatTimestamp (video: Video) { |
177 | const start = video.playlistElement.startTimestamp | |
178 | const stop = video.playlistElement.stopTimestamp | |
179 | ||
180 | const startFormatted = secondsToTime(start, true, ':') | |
181 | const stopFormatted = secondsToTime(stop, true, ':') | |
182 | ||
183 | if (start === null && stop === null) return '' | |
184 | ||
185 | if (start !== null && stop === null) return this.i18n('Starts at ') + startFormatted | |
186 | if (start === null && stop !== null) return this.i18n('Stops at ') + stopFormatted | |
187 | ||
188 | return this.i18n('Starts at ') + startFormatted + this.i18n(' and stops at ') + stopFormatted | |
189 | } | |
190 | ||
191 | onDropdownOpenChange () { | |
192 | this.displayTimestampOptions = false | |
193 | } | |
194 | ||
195 | toggleDisplayTimestampsOptions (event: Event, video: Video) { | |
196 | event.preventDefault() | |
197 | ||
198 | this.displayTimestampOptions = !this.displayTimestampOptions | |
199 | ||
200 | if (this.displayTimestampOptions === true) { | |
201 | this.timestampOptions = { | |
202 | startTimestampEnabled: false, | |
203 | stopTimestampEnabled: false, | |
204 | startTimestamp: 0, | |
205 | stopTimestamp: video.duration | |
206 | } | |
207 | ||
208 | if (video.playlistElement.startTimestamp) { | |
209 | this.timestampOptions.startTimestampEnabled = true | |
210 | this.timestampOptions.startTimestamp = video.playlistElement.startTimestamp | |
211 | } | |
212 | ||
213 | if (video.playlistElement.stopTimestamp) { | |
214 | this.timestampOptions.stopTimestampEnabled = true | |
215 | this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp | |
216 | } | |
217 | } | |
218 | } | |
219 | ||
f0a39880 C |
220 | private loadElements () { |
221 | this.videoService.getPlaylistVideos(this.videoPlaylistId, this.pagination) | |
222 | .subscribe(({ totalVideos, videos }) => { | |
223 | this.videos = this.videos.concat(videos) | |
224 | this.pagination.totalItems = totalVideos | |
225 | }) | |
226 | } | |
c5a1ae50 C |
227 | |
228 | private loadPlaylistInfo () { | |
229 | this.videoPlaylistService.getVideoPlaylist(this.videoPlaylistId) | |
230 | .subscribe(playlist => { | |
231 | this.playlist = playlist | |
232 | }) | |
233 | } | |
15e9d5ca C |
234 | |
235 | private reorderClientPositions () { | |
236 | let i = 1 | |
237 | ||
238 | for (const video of this.videos) { | |
239 | video.playlistElement.position = i | |
240 | i++ | |
241 | } | |
242 | } | |
f0a39880 | 243 | } |