aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+videos/+video-watch/video-rate.component.ts
blob: 89a666a627f43f060c1da6014d305f27508d6f42 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { Hotkey, HotkeysService } from 'angular2-hotkeys'
import { Observable } from 'rxjs'
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'
import { Notifier, ScreenService } from '@app/core'
import { VideoDetails, VideoService } from '@app/shared/shared-main'
import { UserVideoRateType } from '@shared/models'

@Component({
  selector: 'my-video-rate',
  templateUrl: './video-rate.component.html',
  styleUrls: [ './video-rate.component.scss' ]
})
export class VideoRateComponent implements OnInit, OnChanges, OnDestroy {
  @Input() video: VideoDetails
  @Input() isUserLoggedIn: boolean

  @Output() userRatingLoaded = new EventEmitter<UserVideoRateType>()
  @Output() rateUpdated = new EventEmitter<UserVideoRateType>()

  userRating: UserVideoRateType

  tooltipLike = ''
  tooltipDislike = ''

  private hotkeys: Hotkey[]

  constructor (
    private videoService: VideoService,
    private notifier: Notifier,
    private hotkeysService: HotkeysService,
    private screenService: ScreenService
  ) { }

  async ngOnInit () {
    // Hide the tooltips for unlogged users in mobile view, this adds confusion with the popover
    if (this.isUserLoggedIn || !this.screenService.isInMobileView()) {
      this.tooltipLike = $localize`Like this video`
      this.tooltipDislike = $localize`Dislike this video`
    }

    if (this.isUserLoggedIn) {
      this.hotkeys = [
        new Hotkey('shift+l', () => {
          this.setLike()
          return false
        }, undefined, $localize`Like the video`),

        new Hotkey('shift+d', () => {
          this.setDislike()
          return false
        }, undefined, $localize`Dislike the video`)
      ]

      this.hotkeysService.add(this.hotkeys)
    }
  }

  ngOnChanges () {
    this.checkUserRating()
  }

  ngOnDestroy () {
    this.hotkeysService.remove(this.hotkeys)
  }

  setLike () {
    if (this.isUserLoggedIn === false) return

    // Already liked this video
    if (this.userRating === 'like') this.setRating('none')
    else this.setRating('like')
  }

  setDislike () {
    if (this.isUserLoggedIn === false) return

    // Already disliked this video
    if (this.userRating === 'dislike') this.setRating('none')
    else this.setRating('dislike')
  }

  getRatePopoverText () {
    if (this.isUserLoggedIn) return undefined

    return $localize`You need to be <a href="/login">logged in</a> to rate this video.`
  }

  private checkUserRating () {
    // Unlogged users do not have ratings
    if (this.isUserLoggedIn === false) return

    this.videoService.getUserVideoRating(this.video.id)
        .subscribe(
          ratingObject => {
            if (!ratingObject) return

            this.userRating = ratingObject.rating
            this.userRatingLoaded.emit(this.userRating)
          },

          err => this.notifier.error(err.message)
        )
  }

  private setRating (nextRating: UserVideoRateType) {
    const ratingMethods: { [id in UserVideoRateType]: (id: number) => Observable<any> } = {
      like: this.videoService.setVideoLike,
      dislike: this.videoService.setVideoDislike,
      none: this.videoService.unsetVideoLike
    }

    ratingMethods[nextRating].call(this.videoService, this.video.id)
          .subscribe(
            () => {
              // Update the video like attribute
              this.updateVideoRating(this.userRating, nextRating)
              this.userRating = nextRating
              this.rateUpdated.emit(this.userRating)
            },

            (err: { message: string }) => this.notifier.error(err.message)
          )
  }

  private updateVideoRating (oldRating: UserVideoRateType, newRating: UserVideoRateType) {
    let likesToIncrement = 0
    let dislikesToIncrement = 0

    if (oldRating) {
      if (oldRating === 'like') likesToIncrement--
      if (oldRating === 'dislike') dislikesToIncrement--
    }

    if (newRating === 'like') likesToIncrement++
    if (newRating === 'dislike') dislikesToIncrement++

    this.video.likes += likesToIncrement
    this.video.dislikes += dislikesToIncrement

    this.video.buildLikeAndDislikePercents()
  }
}