diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-10-09 14:28:44 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-10-09 14:28:44 +0200 |
commit | a685e25ca05f08ad1b3f7fbaccc8744727bd8d27 (patch) | |
tree | e50fbc2f260a0017113c4668c3c0f3d2fd76ab87 /client/src/app/videos/+video-watch/video-watch.component.ts | |
parent | 2ed6a0aedc2d2f6b1ac2fd9a1ac137772831f713 (diff) | |
download | PeerTube-a685e25ca05f08ad1b3f7fbaccc8744727bd8d27.tar.gz PeerTube-a685e25ca05f08ad1b3f7fbaccc8744727bd8d27.tar.zst PeerTube-a685e25ca05f08ad1b3f7fbaccc8744727bd8d27.zip |
Try to optimize frontend
Diffstat (limited to 'client/src/app/videos/+video-watch/video-watch.component.ts')
-rw-r--r-- | client/src/app/videos/+video-watch/video-watch.component.ts | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts new file mode 100644 index 000000000..874dd5997 --- /dev/null +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -0,0 +1,299 @@ | |||
1 | import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core' | ||
2 | import { ActivatedRoute, Router } from '@angular/router' | ||
3 | import { Observable } from 'rxjs/Observable' | ||
4 | import { Subscription } from 'rxjs/Subscription' | ||
5 | |||
6 | import videojs from 'video.js' | ||
7 | import '../../../assets/player/peertube-videojs-plugin' | ||
8 | |||
9 | import { MetaService } from '@ngx-meta/core' | ||
10 | import { NotificationsService } from 'angular2-notifications' | ||
11 | |||
12 | import { AuthService, ConfirmService } from '../../core' | ||
13 | import { VideoMagnetComponent } from './video-magnet.component' | ||
14 | import { VideoShareComponent } from './video-share.component' | ||
15 | import { VideoReportComponent } from './video-report.component' | ||
16 | import { Video, VideoService } from '../shared' | ||
17 | import { WebTorrentService } from './webtorrent.service' | ||
18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | ||
19 | |||
20 | @Component({ | ||
21 | selector: 'my-video-watch', | ||
22 | templateUrl: './video-watch.component.html', | ||
23 | styleUrls: [ './video-watch.component.scss' ] | ||
24 | }) | ||
25 | export class VideoWatchComponent implements OnInit, OnDestroy { | ||
26 | @ViewChild('videoMagnetModal') videoMagnetModal: VideoMagnetComponent | ||
27 | @ViewChild('videoShareModal') videoShareModal: VideoShareComponent | ||
28 | @ViewChild('videoReportModal') videoReportModal: VideoReportComponent | ||
29 | |||
30 | downloadSpeed: number | ||
31 | error = false | ||
32 | loading = false | ||
33 | numPeers: number | ||
34 | player: videojs.Player | ||
35 | playerElement: HTMLMediaElement | ||
36 | uploadSpeed: number | ||
37 | userRating: UserVideoRateType = null | ||
38 | video: Video = null | ||
39 | videoNotFound = false | ||
40 | |||
41 | private paramsSub: Subscription | ||
42 | |||
43 | constructor ( | ||
44 | private elementRef: ElementRef, | ||
45 | private route: ActivatedRoute, | ||
46 | private router: Router, | ||
47 | private videoService: VideoService, | ||
48 | private confirmService: ConfirmService, | ||
49 | private metaService: MetaService, | ||
50 | private authService: AuthService, | ||
51 | private notificationsService: NotificationsService | ||
52 | ) {} | ||
53 | |||
54 | ngOnInit () { | ||
55 | this.paramsSub = this.route.params.subscribe(routeParams => { | ||
56 | let uuid = routeParams['uuid'] | ||
57 | this.videoService.getVideo(uuid).subscribe( | ||
58 | video => this.onVideoFetched(video), | ||
59 | |||
60 | error => { | ||
61 | console.error(error) | ||
62 | this.videoNotFound = true | ||
63 | } | ||
64 | ) | ||
65 | }) | ||
66 | } | ||
67 | |||
68 | ngOnDestroy () { | ||
69 | // Remove player if it exists | ||
70 | if (this.videoNotFound === false) { | ||
71 | videojs(this.playerElement).dispose() | ||
72 | } | ||
73 | |||
74 | // Unsubscribe subscriptions | ||
75 | this.paramsSub.unsubscribe() | ||
76 | } | ||
77 | |||
78 | setLike () { | ||
79 | if (this.isUserLoggedIn() === false) return | ||
80 | // Already liked this video | ||
81 | if (this.userRating === 'like') return | ||
82 | |||
83 | this.videoService.setVideoLike(this.video.id) | ||
84 | .subscribe( | ||
85 | () => { | ||
86 | // Update the video like attribute | ||
87 | this.updateVideoRating(this.userRating, 'like') | ||
88 | this.userRating = 'like' | ||
89 | }, | ||
90 | |||
91 | err => this.notificationsService.error('Error', err.message) | ||
92 | ) | ||
93 | } | ||
94 | |||
95 | setDislike () { | ||
96 | if (this.isUserLoggedIn() === false) return | ||
97 | // Already disliked this video | ||
98 | if (this.userRating === 'dislike') return | ||
99 | |||
100 | this.videoService.setVideoDislike(this.video.id) | ||
101 | .subscribe( | ||
102 | () => { | ||
103 | // Update the video dislike attribute | ||
104 | this.updateVideoRating(this.userRating, 'dislike') | ||
105 | this.userRating = 'dislike' | ||
106 | }, | ||
107 | |||
108 | err => this.notificationsService.error('Error', err.message) | ||
109 | ) | ||
110 | } | ||
111 | |||
112 | removeVideo (event: Event) { | ||
113 | event.preventDefault() | ||
114 | |||
115 | this.confirmService.confirm('Do you really want to delete this video?', 'Delete').subscribe( | ||
116 | res => { | ||
117 | if (res === false) return | ||
118 | |||
119 | this.videoService.removeVideo(this.video.id) | ||
120 | .subscribe( | ||
121 | status => { | ||
122 | this.notificationsService.success('Success', `Video ${this.video.name} deleted.`) | ||
123 | // Go back to the video-list. | ||
124 | this.router.navigate(['/videos/list']) | ||
125 | }, | ||
126 | |||
127 | error => this.notificationsService.error('Error', error.text) | ||
128 | ) | ||
129 | } | ||
130 | ) | ||
131 | } | ||
132 | |||
133 | blacklistVideo (event: Event) { | ||
134 | event.preventDefault() | ||
135 | |||
136 | this.confirmService.confirm('Do you really want to blacklist this video ?', 'Blacklist').subscribe( | ||
137 | res => { | ||
138 | if (res === false) return | ||
139 | |||
140 | this.videoService.blacklistVideo(this.video.id) | ||
141 | .subscribe( | ||
142 | status => { | ||
143 | this.notificationsService.success('Success', `Video ${this.video.name} had been blacklisted.`) | ||
144 | this.router.navigate(['/videos/list']) | ||
145 | }, | ||
146 | |||
147 | error => this.notificationsService.error('Error', error.text) | ||
148 | ) | ||
149 | } | ||
150 | ) | ||
151 | } | ||
152 | |||
153 | showReportModal (event: Event) { | ||
154 | event.preventDefault() | ||
155 | this.videoReportModal.show() | ||
156 | } | ||
157 | |||
158 | showShareModal () { | ||
159 | this.videoShareModal.show() | ||
160 | } | ||
161 | |||
162 | showMagnetUriModal (event: Event) { | ||
163 | event.preventDefault() | ||
164 | this.videoMagnetModal.show() | ||
165 | } | ||
166 | |||
167 | isUserLoggedIn () { | ||
168 | return this.authService.isLoggedIn() | ||
169 | } | ||
170 | |||
171 | canUserUpdateVideo () { | ||
172 | return this.video.isUpdatableBy(this.authService.getUser()) | ||
173 | } | ||
174 | |||
175 | isVideoRemovable () { | ||
176 | return this.video.isRemovableBy(this.authService.getUser()) | ||
177 | } | ||
178 | |||
179 | isVideoBlacklistable () { | ||
180 | return this.video.isBlackistableBy(this.authService.getUser()) | ||
181 | } | ||
182 | |||
183 | private handleError (err: any) { | ||
184 | const errorMessage: string = typeof err === 'string' ? err : err.message | ||
185 | let message = '' | ||
186 | |||
187 | if (errorMessage.indexOf('http error') !== -1) { | ||
188 | message = 'Cannot fetch video from server, maybe down.' | ||
189 | } else { | ||
190 | message = errorMessage | ||
191 | } | ||
192 | |||
193 | this.notificationsService.error('Error', message) | ||
194 | } | ||
195 | |||
196 | private checkUserRating () { | ||
197 | // Unlogged users do not have ratings | ||
198 | if (this.isUserLoggedIn() === false) return | ||
199 | |||
200 | this.videoService.getUserVideoRating(this.video.id) | ||
201 | .subscribe( | ||
202 | ratingObject => { | ||
203 | if (ratingObject) { | ||
204 | this.userRating = ratingObject.rating | ||
205 | } | ||
206 | }, | ||
207 | |||
208 | err => this.notificationsService.error('Error', err.message) | ||
209 | ) | ||
210 | } | ||
211 | |||
212 | private onVideoFetched (video: Video) { | ||
213 | this.video = video | ||
214 | |||
215 | let observable | ||
216 | if (this.video.isVideoNSFWForUser(this.authService.getUser())) { | ||
217 | observable = this.confirmService.confirm('This video is not safe for work. Are you sure you want to watch it?', 'NSFW') | ||
218 | } else { | ||
219 | observable = Observable.of(true) | ||
220 | } | ||
221 | |||
222 | observable.subscribe( | ||
223 | res => { | ||
224 | if (res === false) { | ||
225 | return this.router.navigate([ '/videos/list' ]) | ||
226 | } | ||
227 | |||
228 | this.playerElement = this.elementRef.nativeElement.querySelector('#video-container') | ||
229 | |||
230 | const videojsOptions = { | ||
231 | controls: true, | ||
232 | autoplay: true, | ||
233 | plugins: { | ||
234 | peertube: { | ||
235 | videoFiles: this.video.files, | ||
236 | playerElement: this.playerElement, | ||
237 | autoplay: true, | ||
238 | peerTubeLink: false | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | const self = this | ||
244 | videojs(this.playerElement, videojsOptions, function () { | ||
245 | self.player = this | ||
246 | this.on('customError', (event, data) => { | ||
247 | self.handleError(data.err) | ||
248 | }) | ||
249 | |||
250 | this.on('torrentInfo', (event, data) => { | ||
251 | self.downloadSpeed = data.downloadSpeed | ||
252 | self.numPeers = data.numPeers | ||
253 | self.uploadSpeed = data.uploadSpeed | ||
254 | }) | ||
255 | }) | ||
256 | |||
257 | this.setOpenGraphTags() | ||
258 | this.checkUserRating() | ||
259 | } | ||
260 | ) | ||
261 | } | ||
262 | |||
263 | private updateVideoRating (oldRating: UserVideoRateType, newRating: VideoRateType) { | ||
264 | let likesToIncrement = 0 | ||
265 | let dislikesToIncrement = 0 | ||
266 | |||
267 | if (oldRating) { | ||
268 | if (oldRating === 'like') likesToIncrement-- | ||
269 | if (oldRating === 'dislike') dislikesToIncrement-- | ||
270 | } | ||
271 | |||
272 | if (newRating === 'like') likesToIncrement++ | ||
273 | if (newRating === 'dislike') dislikesToIncrement++ | ||
274 | |||
275 | this.video.likes += likesToIncrement | ||
276 | this.video.dislikes += dislikesToIncrement | ||
277 | } | ||
278 | |||
279 | private setOpenGraphTags () { | ||
280 | this.metaService.setTitle(this.video.name) | ||
281 | |||
282 | this.metaService.setTag('og:type', 'video') | ||
283 | |||
284 | this.metaService.setTag('og:title', this.video.name) | ||
285 | this.metaService.setTag('name', this.video.name) | ||
286 | |||
287 | this.metaService.setTag('og:description', this.video.description) | ||
288 | this.metaService.setTag('description', this.video.description) | ||
289 | |||
290 | this.metaService.setTag('og:image', this.video.previewPath) | ||
291 | |||
292 | this.metaService.setTag('og:duration', this.video.duration.toString()) | ||
293 | |||
294 | this.metaService.setTag('og:site_name', 'PeerTube') | ||
295 | |||
296 | this.metaService.setTag('og:url', window.location.href) | ||
297 | this.metaService.setTag('url', window.location.href) | ||
298 | } | ||
299 | } | ||