79505c779acddbbf0fc4b18f9edbc4ea050c668a
[oweals/peertube.git] / client / src / app / videos / +video-watch / comment / video-comment-add.component.ts
1 import { Observable } from 'rxjs'
2 import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
3 import { Router } from '@angular/router'
4 import { Notifier, User } from '@app/core'
5 import { FormReactive, FormValidatorService, VideoCommentValidatorsService } from '@app/shared/shared-forms'
6 import { Video } from '@app/shared/shared-main'
7 import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
8 import { VideoCommentCreate } from '@shared/models'
9 import { VideoComment } from './video-comment.model'
10 import { VideoCommentService } from './video-comment.service'
11
12 @Component({
13   selector: 'my-video-comment-add',
14   templateUrl: './video-comment-add.component.html',
15   styleUrls: ['./video-comment-add.component.scss']
16 })
17 export class VideoCommentAddComponent extends FormReactive implements OnInit {
18   @Input() user: User
19   @Input() video: Video
20   @Input() parentComment: VideoComment
21   @Input() parentComments: VideoComment[]
22   @Input() focusOnInit = false
23
24   @Output() commentCreated = new EventEmitter<VideoComment>()
25   @Output() cancel = new EventEmitter()
26
27   @ViewChild('visitorModal', { static: true }) visitorModal: NgbModal
28   @ViewChild('textarea', { static: true }) textareaElement: ElementRef
29
30   addingComment = false
31
32   constructor (
33     protected formValidatorService: FormValidatorService,
34     private videoCommentValidatorsService: VideoCommentValidatorsService,
35     private notifier: Notifier,
36     private videoCommentService: VideoCommentService,
37     private modalService: NgbModal,
38     private router: Router
39   ) {
40     super()
41   }
42
43   ngOnInit () {
44     this.buildForm({
45       text: this.videoCommentValidatorsService.VIDEO_COMMENT_TEXT
46     })
47
48     if (this.user) {
49       if (this.focusOnInit === true) {
50         this.textareaElement.nativeElement.focus()
51       }
52
53       if (this.parentComment) {
54         const mentions = this.parentComments
55           .filter(c => c.account && c.account.id !== this.user.account.id) // Don't add mention of ourselves
56           .map(c => '@' + c.by)
57
58         const mentionsSet = new Set(mentions)
59         const mentionsText = Array.from(mentionsSet).join(' ') + ' '
60
61         this.form.patchValue({ text: mentionsText })
62       }
63     }
64   }
65
66   onValidKey () {
67     this.check()
68     if (!this.form.valid) return
69
70     this.formValidated()
71   }
72
73   openVisitorModal (event: any) {
74     if (this.user === null) { // we only open it for visitors
75       // fixing ng-bootstrap ModalService and the "Expression Changed After It Has Been Checked" Error
76       event.srcElement.blur()
77       event.preventDefault()
78
79       this.modalService.open(this.visitorModal)
80     }
81   }
82
83   hideVisitorModal () {
84     this.modalService.dismissAll()
85   }
86
87   formValidated () {
88     // If we validate very quickly the comment form, we might comment twice
89     if (this.addingComment) return
90
91     this.addingComment = true
92
93     const commentCreate: VideoCommentCreate = this.form.value
94     let obs: Observable<VideoComment>
95
96     if (this.parentComment) {
97       obs = this.addCommentReply(commentCreate)
98     } else {
99       obs = this.addCommentThread(commentCreate)
100     }
101
102     obs.subscribe(
103       comment => {
104         this.addingComment = false
105         this.commentCreated.emit(comment)
106         this.form.reset()
107       },
108
109       err => {
110         this.addingComment = false
111
112         this.notifier.error(err.text)
113       }
114     )
115   }
116
117   isAddButtonDisplayed () {
118     return this.form.value['text']
119   }
120
121   getUri () {
122     return window.location.href
123   }
124
125   getAvatarUrl () {
126     if (this.user) return this.user.accountAvatarUrl
127     return window.location.origin + '/client/assets/images/default-avatar.png'
128   }
129
130   gotoLogin () {
131     this.hideVisitorModal()
132     this.router.navigate([ '/login' ])
133   }
134
135   cancelCommentReply () {
136     this.cancel.emit(null)
137     this.form.value['text'] = this.textareaElement.nativeElement.value = ''
138   }
139
140   private addCommentReply (commentCreate: VideoCommentCreate) {
141     return this.videoCommentService
142       .addCommentReply(this.video.id, this.parentComment.id, commentCreate)
143   }
144
145   private addCommentThread (commentCreate: VideoCommentCreate) {
146     return this.videoCommentService
147       .addCommentThread(this.video.id, commentCreate)
148   }
149 }