diff options
Diffstat (limited to 'client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts')
-rw-r--r-- | client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts b/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts new file mode 100644 index 000000000..89a666a62 --- /dev/null +++ b/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts | |||
@@ -0,0 +1,142 @@ | |||
1 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' | ||
2 | import { Observable } from 'rxjs' | ||
3 | import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core' | ||
4 | import { Notifier, ScreenService } from '@app/core' | ||
5 | import { VideoDetails, VideoService } from '@app/shared/shared-main' | ||
6 | import { UserVideoRateType } from '@shared/models' | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'my-video-rate', | ||
10 | templateUrl: './video-rate.component.html', | ||
11 | styleUrls: [ './video-rate.component.scss' ] | ||
12 | }) | ||
13 | export class VideoRateComponent implements OnInit, OnChanges, OnDestroy { | ||
14 | @Input() video: VideoDetails | ||
15 | @Input() isUserLoggedIn: boolean | ||
16 | |||
17 | @Output() userRatingLoaded = new EventEmitter<UserVideoRateType>() | ||
18 | @Output() rateUpdated = new EventEmitter<UserVideoRateType>() | ||
19 | |||
20 | userRating: UserVideoRateType | ||
21 | |||
22 | tooltipLike = '' | ||
23 | tooltipDislike = '' | ||
24 | |||
25 | private hotkeys: Hotkey[] | ||
26 | |||
27 | constructor ( | ||
28 | private videoService: VideoService, | ||
29 | private notifier: Notifier, | ||
30 | private hotkeysService: HotkeysService, | ||
31 | private screenService: ScreenService | ||
32 | ) { } | ||
33 | |||
34 | async ngOnInit () { | ||
35 | // Hide the tooltips for unlogged users in mobile view, this adds confusion with the popover | ||
36 | if (this.isUserLoggedIn || !this.screenService.isInMobileView()) { | ||
37 | this.tooltipLike = $localize`Like this video` | ||
38 | this.tooltipDislike = $localize`Dislike this video` | ||
39 | } | ||
40 | |||
41 | if (this.isUserLoggedIn) { | ||
42 | this.hotkeys = [ | ||
43 | new Hotkey('shift+l', () => { | ||
44 | this.setLike() | ||
45 | return false | ||
46 | }, undefined, $localize`Like the video`), | ||
47 | |||
48 | new Hotkey('shift+d', () => { | ||
49 | this.setDislike() | ||
50 | return false | ||
51 | }, undefined, $localize`Dislike the video`) | ||
52 | ] | ||
53 | |||
54 | this.hotkeysService.add(this.hotkeys) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | ngOnChanges () { | ||
59 | this.checkUserRating() | ||
60 | } | ||
61 | |||
62 | ngOnDestroy () { | ||
63 | this.hotkeysService.remove(this.hotkeys) | ||
64 | } | ||
65 | |||
66 | setLike () { | ||
67 | if (this.isUserLoggedIn === false) return | ||
68 | |||
69 | // Already liked this video | ||
70 | if (this.userRating === 'like') this.setRating('none') | ||
71 | else this.setRating('like') | ||
72 | } | ||
73 | |||
74 | setDislike () { | ||
75 | if (this.isUserLoggedIn === false) return | ||
76 | |||
77 | // Already disliked this video | ||
78 | if (this.userRating === 'dislike') this.setRating('none') | ||
79 | else this.setRating('dislike') | ||
80 | } | ||
81 | |||
82 | getRatePopoverText () { | ||
83 | if (this.isUserLoggedIn) return undefined | ||
84 | |||
85 | return $localize`You need to be <a href="/login">logged in</a> to rate this video.` | ||
86 | } | ||
87 | |||
88 | private checkUserRating () { | ||
89 | // Unlogged users do not have ratings | ||
90 | if (this.isUserLoggedIn === false) return | ||
91 | |||
92 | this.videoService.getUserVideoRating(this.video.id) | ||
93 | .subscribe( | ||
94 | ratingObject => { | ||
95 | if (!ratingObject) return | ||
96 | |||
97 | this.userRating = ratingObject.rating | ||
98 | this.userRatingLoaded.emit(this.userRating) | ||
99 | }, | ||
100 | |||
101 | err => this.notifier.error(err.message) | ||
102 | ) | ||
103 | } | ||
104 | |||
105 | private setRating (nextRating: UserVideoRateType) { | ||
106 | const ratingMethods: { [id in UserVideoRateType]: (id: number) => Observable<any> } = { | ||
107 | like: this.videoService.setVideoLike, | ||
108 | dislike: this.videoService.setVideoDislike, | ||
109 | none: this.videoService.unsetVideoLike | ||
110 | } | ||
111 | |||
112 | ratingMethods[nextRating].call(this.videoService, this.video.id) | ||
113 | .subscribe( | ||
114 | () => { | ||
115 | // Update the video like attribute | ||
116 | this.updateVideoRating(this.userRating, nextRating) | ||
117 | this.userRating = nextRating | ||
118 | this.rateUpdated.emit(this.userRating) | ||
119 | }, | ||
120 | |||
121 | (err: { message: string }) => this.notifier.error(err.message) | ||
122 | ) | ||
123 | } | ||
124 | |||
125 | private updateVideoRating (oldRating: UserVideoRateType, newRating: UserVideoRateType) { | ||
126 | let likesToIncrement = 0 | ||
127 | let dislikesToIncrement = 0 | ||
128 | |||
129 | if (oldRating) { | ||
130 | if (oldRating === 'like') likesToIncrement-- | ||
131 | if (oldRating === 'dislike') dislikesToIncrement-- | ||
132 | } | ||
133 | |||
134 | if (newRating === 'like') likesToIncrement++ | ||
135 | if (newRating === 'dislike') dislikesToIncrement++ | ||
136 | |||
137 | this.video.likes += likesToIncrement | ||
138 | this.video.dislikes += dislikesToIncrement | ||
139 | |||
140 | this.video.buildLikeAndDislikePercents() | ||
141 | } | ||
142 | } | ||